blob: c3cec2ceeaa377d67751dad6727998cee3f7577c [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/android/remote/remote_media_player_manager.h"
#include "chrome/browser/android/tab_android.h"
#include "chrome/common/chrome_content_client.h"
#include "content/common/media/media_player_messages_android.h"
#include "third_party/WebKit/public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/android/java_bitmap.h"
using media::MediaPlayerAndroid;
static const int MAX_POSTER_BITMAP_SIZE = 1024 * 1024;
namespace remote_media {
RemoteMediaPlayerManager::RemoteMediaPlayerManager(
content::RenderFrameHost* render_frame_host)
: BrowserMediaPlayerManager(render_frame_host),
weak_ptr_factory_(this) {
}
RemoteMediaPlayerManager::~RemoteMediaPlayerManager() {
for (auto& player : alternative_players_)
player.release()->DeleteOnCorrectThread();
alternative_players_.clear();
}
void RemoteMediaPlayerManager::OnStart(int player_id) {
RemoteMediaPlayerBridge* remote_player = GetRemotePlayer(player_id);
if (remote_player && IsPlayingRemotely(player_id))
remote_player->Start();
BrowserMediaPlayerManager::OnStart(player_id);
}
void RemoteMediaPlayerManager::OnInitialize(
const MediaPlayerHostMsg_Initialize_Params& media_params) {
BrowserMediaPlayerManager::OnInitialize(media_params);
if (GetPlayer(media_params.player_id)) {
RemoteMediaPlayerBridge* remote_player =
CreateRemoteMediaPlayer(media_params.player_id);
remote_player->OnPlayerCreated();
}
}
void RemoteMediaPlayerManager::OnDestroyPlayer(int player_id) {
RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
if (player)
player->OnPlayerDestroyed();
poster_urls_.erase(player_id);
BrowserMediaPlayerManager::OnDestroyPlayer(player_id);
}
void RemoteMediaPlayerManager::OnSuspendAndReleaseResources(int player_id) {
// We only want to release resources of local players.
if (!IsPlayingRemotely(player_id))
BrowserMediaPlayerManager::OnSuspendAndReleaseResources(player_id);
}
void RemoteMediaPlayerManager::OnRequestRemotePlayback(int player_id) {
RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
if (player)
player->RequestRemotePlayback();
}
void RemoteMediaPlayerManager::OnRequestRemotePlaybackControl(int player_id) {
RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
if (player)
player->RequestRemotePlaybackControl();
}
void RemoteMediaPlayerManager::OnRequestRemotePlaybackStop(int player_id) {
RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
if (player)
player->RequestRemotePlaybackStop();
}
bool RemoteMediaPlayerManager::IsPlayingRemotely(int player_id) {
return players_playing_remotely_.count(player_id) != 0;
}
int RemoteMediaPlayerManager::GetTabId() {
if (!web_contents())
return -1;
TabAndroid* tab = TabAndroid::FromWebContents(web_contents());
if (!tab)
return -1;
return tab->GetAndroidId();
}
void RemoteMediaPlayerManager::FetchPosterBitmap(int player_id) {
RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
if (poster_urls_.count(player_id) == 0 ||
poster_urls_[player_id].is_empty()) {
if (player)
player->SetPosterBitmap(std::vector<SkBitmap>());
return;
}
content::WebContents::ImageDownloadCallback callback =
base::BindOnce(&RemoteMediaPlayerManager::DidDownloadPoster,
weak_ptr_factory_.GetWeakPtr(), player_id);
web_contents()->DownloadImage(
poster_urls_[player_id],
false, // is_favicon, false so that cookies will be used.
MAX_POSTER_BITMAP_SIZE, // max_bitmap_size, 0 means no limit.
false, // normal cache policy.
std::move(callback));
}
void RemoteMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
// OnSetPoster is called when the attibutes of the video element are parsed,
// which may be before OnInitialize is called, so we can't assume that the
// players wil exist.
poster_urls_[player_id] = url;
}
void RemoteMediaPlayerManager::ReleaseResources(int player_id) {
if (IsPlayingRemotely(player_id))
return;
BrowserMediaPlayerManager::ReleaseResources(player_id);
}
void RemoteMediaPlayerManager::DidDownloadPoster(
int player_id,
int id,
int http_status_code,
const GURL& image_url,
const std::vector<SkBitmap>& bitmaps,
const std::vector<gfx::Size>& original_bitmap_sizes) {
RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
if (player)
player->SetPosterBitmap(bitmaps);
}
RemoteMediaPlayerBridge* RemoteMediaPlayerManager::CreateRemoteMediaPlayer(
int player_id) {
alternative_players_.push_back(std::make_unique<RemoteMediaPlayerBridge>(
player_id, GetUserAgent(), this));
RemoteMediaPlayerBridge* remote =
static_cast<RemoteMediaPlayerBridge*>(alternative_players_.back().get());
remote->Initialize();
return remote;
}
bool RemoteMediaPlayerManager::SwapCurrentPlayer(int player_id) {
// Find the alternative player to swap the current one with.
auto it = GetAlternativePlayer(player_id);
if (it == alternative_players_.end())
return false;
// Release ownership of the alternative player.
std::unique_ptr<MediaPlayerAndroid> old_player =
SwapPlayer(player_id, std::move(*it));
alternative_players_.erase(it);
if (!old_player) {
return false;
}
alternative_players_.push_back(std::move(old_player));
return true;
}
void RemoteMediaPlayerManager::SwitchToRemotePlayer(
int player_id,
const std::string& casting_message) {
DCHECK(!IsPlayingRemotely(player_id));
if (!SwapCurrentPlayer(player_id))
return;
players_playing_remotely_.insert(player_id);
Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id));
Send(new MediaPlayerMsg_ConnectedToRemoteDevice(RoutingID(), player_id,
casting_message));
// The remote player will want the poster bitmap, however, to avoid wasting
// memory we don't fetch it until we are likely to need it.
FetchPosterBitmap(player_id);
}
void RemoteMediaPlayerManager::SwitchToLocalPlayer(int player_id) {
DCHECK(IsPlayingRemotely(player_id));
SwapCurrentPlayer(player_id);
players_playing_remotely_.erase(player_id);
Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(RoutingID(), player_id));
}
void RemoteMediaPlayerManager::ReplaceRemotePlayerWithLocal(int player_id) {
if (!IsPlayingRemotely(player_id))
return;
MediaPlayerAndroid* remote_player = GetPlayer(player_id);
remote_player->Pause(true);
Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(RoutingID(), player_id));
GetLocalPlayer(player_id)->SeekTo(remote_player->GetCurrentTime());
SwapCurrentPlayer(player_id);
remote_player->Release();
players_playing_remotely_.erase(player_id);
}
void RemoteMediaPlayerManager::OnRemoteDeviceUnselected(int player_id) {
ReplaceRemotePlayerWithLocal(player_id);
}
void RemoteMediaPlayerManager::OnRemotePlaybackStarted(int player_id) {
Send(new MediaPlayerMsg_RemotePlaybackStarted(RoutingID(), player_id));
}
void RemoteMediaPlayerManager::OnRemotePlaybackFinished(int player_id) {
ReplaceRemotePlayerWithLocal(player_id);
}
void RemoteMediaPlayerManager::OnRouteAvailabilityChanged(
int player_id, blink::WebRemotePlaybackAvailability availability) {
Send(new MediaPlayerMsg_RemoteRouteAvailabilityChanged(
RoutingID(), player_id, availability));
}
void RemoteMediaPlayerManager::OnCancelledRemotePlaybackRequest(int player_id) {
Send(new MediaPlayerMsg_CancelledRemotePlaybackRequest(
RoutingID(), player_id));
}
void RemoteMediaPlayerManager::ReleaseFullscreenPlayer(
MediaPlayerAndroid* player) {
int player_id = player->player_id();
// Release the original player's resources, not the current fullscreen player
// (which is the remote player).
if (IsPlayingRemotely(player_id))
GetLocalPlayer(player_id)->Release();
else
BrowserMediaPlayerManager::ReleaseFullscreenPlayer(player);
}
void RemoteMediaPlayerManager::OnPlaying(int player_id) {
Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(),player_id));
}
void RemoteMediaPlayerManager::OnPaused(int player_id) {
Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(),player_id));
}
std::vector<std::unique_ptr<MediaPlayerAndroid>>::iterator
RemoteMediaPlayerManager::GetAlternativePlayer(int player_id) {
for (auto it = alternative_players_.begin(); it != alternative_players_.end();
++it) {
if ((*it)->player_id() == player_id) {
return it;
}
}
return alternative_players_.end();
}
RemoteMediaPlayerBridge* RemoteMediaPlayerManager::GetRemotePlayer(
int player_id) {
if (IsPlayingRemotely(player_id))
return static_cast<RemoteMediaPlayerBridge*>(GetPlayer(player_id));
auto it = GetAlternativePlayer(player_id);
if (it == alternative_players_.end())
return nullptr;
return static_cast<RemoteMediaPlayerBridge*>(it->get());
}
MediaPlayerAndroid* RemoteMediaPlayerManager::GetLocalPlayer(int player_id) {
if (!IsPlayingRemotely(player_id))
return GetPlayer(player_id);
auto it = GetAlternativePlayer(player_id);
if (it == alternative_players_.end())
return nullptr;
return it->get();
}
void RemoteMediaPlayerManager::OnMediaMetadataChanged(int player_id,
base::TimeDelta duration,
int width,
int height,
bool success) {
if (IsPlayingRemotely(player_id)) {
MediaPlayerAndroid* local_player = GetLocalPlayer(player_id);
Send(new MediaPlayerMsg_MediaMetadataChanged(
RoutingID(), player_id, duration, local_player->GetVideoWidth(),
local_player->GetVideoHeight(), success));
} else {
BrowserMediaPlayerManager::OnMediaMetadataChanged(player_id, duration,
width, height, success);
}
}
} // namespace remote_media