0

Upstream fullscreen video implementation for android

BUG=136677


Review URL: https://chromiumcodereview.appspot.com/10979047

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@160431 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
qinmin@chromium.org
2012-10-05 18:44:22 +00:00
parent e7cd01bc32
commit 3e7daca6a6
25 changed files with 544 additions and 525 deletions

@ -7,38 +7,32 @@
#include "base/android/jni_android.h"
#include "base/command_line.h"
#include "base/logging.h"
#if !defined(ANDROID_UPSTREAM_BRINGUP)
#include "content/browser/media/media_player_delegate_android.h"
#endif
#include "content/browser/android/media_player_manager_android.h"
#include "content/common/android/surface_callback.h"
#include "content/common/android/surface_texture_peer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "jni/ContentVideoView_jni.h"
#include "webkit/media/android/media_metadata_android.h"
using base::android::AttachCurrentThread;
using base::android::CheckException;
using base::android::ScopedJavaGlobalRef;
// The timeout value we should wait after user click the back button on the
// fullscreen view.
static const int kTimeoutMillseconds = 1000;
// ----------------------------------------------------------------------------
// Methods that call to Java via JNI
// ----------------------------------------------------------------------------
namespace content {
// static
bool ContentVideoView::RegisterContentVideoView(JNIEnv* env) {
return RegisterNativesImpl(env);
}
void ContentVideoView::CreateContentVideoView(
MediaPlayerDelegateAndroid* player) {
player_ = player;
ContentVideoView::ContentVideoView(MediaPlayerManagerAndroid* manager)
: manager_(manager) {
}
ContentVideoView::~ContentVideoView() {
DestroyContentVideoView();
}
void ContentVideoView::CreateContentVideoView() {
if (j_content_video_view_.is_null()) {
JNIEnv* env = AttachCurrentThread();
j_content_video_view_.Reset(Java_ContentVideoView_createContentVideoView(
@ -94,198 +88,62 @@ void ContentVideoView::UpdateMediaMetadata() {
UpdateMediaMetadata(AttachCurrentThread(), j_content_video_view_.obj());
}
// ----------------------------------------------------------------------------
ContentVideoView::ContentVideoView() : player_(NULL) {
}
ContentVideoView::~ContentVideoView() {
player_ = NULL;
// If the browser process crashed, just kill the fullscreen view.
DestroyContentVideoView();
}
// ----------------------------------------------------------------------------
// All these functions are called on UI thread
int ContentVideoView::GetVideoWidth(JNIEnv*, jobject obj) const {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return player_ ? player_->GetVideoWidth() : 0;
#else
return 0;
#endif
media::MediaPlayerBridge* player = manager_->GetFullscreenPlayer();
return player ? player->GetVideoWidth() : 0;
}
int ContentVideoView::GetVideoHeight(JNIEnv*, jobject obj) const {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return player_ ? player_->GetVideoHeight() : 0;
#else
return 0;
#endif
media::MediaPlayerBridge* player = manager_->GetFullscreenPlayer();
return player ? player->GetVideoHeight() : 0;
}
int ContentVideoView::GetDurationInMilliSeconds(JNIEnv*, jobject obj) const {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return player_ ? ConvertSecondsToMilliSeconds(player_->Duration()) : -1;
#else
return -1;
#endif
media::MediaPlayerBridge* player = manager_->GetFullscreenPlayer();
return player ? player->GetDuration().InMilliseconds() : -1;
}
int ContentVideoView::GetCurrentPosition(JNIEnv*, jobject obj) const {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return player_ ? ConvertSecondsToMilliSeconds(player_->CurrentTime()) : 0;
#else
return 0;
#endif
media::MediaPlayerBridge* player = manager_->GetFullscreenPlayer();
return player ? player->GetCurrentTime().InMilliseconds() : 0;
}
bool ContentVideoView::IsPlaying(JNIEnv*, jobject obj) {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return player_ ? player_->IsPlaying() : false;
#else
return false;
#endif
media::MediaPlayerBridge* player = manager_->GetFullscreenPlayer();
return player ? player->IsPlaying() : false;
}
void ContentVideoView::SeekTo(JNIEnv*, jobject obj, jint msec) {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (player_)
player_->Seek(static_cast<float>(msec / 1000.0));
#endif
}
webkit_media::MediaMetadataAndroid* ContentVideoView::GetMediaMetadata() {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!player_)
return NULL;
return new webkit_media::MediaMetadataAndroid(player_->GetVideoWidth(),
player_->GetVideoHeight(),
base::TimeDelta::FromSeconds(
player_->Duration()),
base::TimeDelta::FromSeconds(
player_->CurrentTime()),
!player_->IsPlaying(),
player_->CanPause(),
player_->CanSeekForward(),
player_->CanSeekForward());
#else
return NULL;
#endif
}
int ContentVideoView::GetPlayerId(JNIEnv*, jobject obj) const {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return player_ ? player_->player_id() : -1;
#else
return -1;
#endif
}
int ContentVideoView::GetRouteId(JNIEnv*, jobject obj) const {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return player_ ? player_->route_id() : -1;
#else
return -1;
#endif
}
int ContentVideoView::GetRenderHandle(JNIEnv*, jobject obj) const {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
static bool single_process =
CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
if (!player_)
return -1;
if (single_process)
return 0;
return player_->render_handle();
#else
return -1;
#endif
manager_->FullscreenPlayerSeek(msec);
}
void ContentVideoView::Play(JNIEnv*, jobject obj) {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (player_)
player_->Play();
#endif
manager_->FullscreenPlayerPlay();
}
void ContentVideoView::Pause(JNIEnv*, jobject obj) {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (player_)
player_->Pause();
#endif
manager_->FullscreenPlayerPause();
}
void ContentVideoView::OnTimeout() {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
#endif
timeout_timer_.Stop();
DestroyContentVideoView();
}
int ContentVideoView::ConvertSecondsToMilliSeconds(float seconds) const {
return static_cast<int>(seconds * 1000);
}
// ----------------------------------------------------------------------------
// Methods called from Java via JNI
// ----------------------------------------------------------------------------
void ContentVideoView::DestroyContentVideoView(JNIEnv*, jobject,
jboolean release_media_player) {
#if !defined(ANDROID_UPSTREAM_BRINGUP)
if (player_) {
player_->ExitFullscreen(release_media_player);
// Fire off a timer so that we will close the fullscreen view in case the
// renderer crashes.
timeout_timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(kTimeoutMillseconds),
this, &ContentVideoView::OnTimeout);
}
#endif
void ContentVideoView::ExitFullscreen(
JNIEnv*, jobject, jboolean release_media_player) {
manager_->ExitFullscreen(release_media_player);
j_content_video_view_.Reset();
}
void ContentVideoView::SetSurface(JNIEnv* env, jobject obj,
jobject surface,
jint route_id,
jint player_id) {
SetSurfaceAsync(env,
surface,
SurfaceTexturePeer::SET_VIDEO_SURFACE_TEXTURE,
route_id,
player_id,
NULL);
jobject surface) {
manager_->SetVideoSurface(surface);
ReleaseSurface(surface);
}
void ContentVideoView::UpdateMediaMetadata(JNIEnv* env, jobject obj) {
scoped_ptr<webkit_media::MediaMetadataAndroid> metadata(GetMediaMetadata());
Java_ContentVideoView_updateMediaMetadata(env,
obj,
metadata->width,
metadata->height,
metadata->duration.InMilliseconds(),
metadata->can_pause,
metadata->can_seek_forward,
metadata->can_seek_backward);
media::MediaPlayerBridge* player = manager_->GetFullscreenPlayer();
if (player)
Java_ContentVideoView_updateMediaMetadata(
env, obj, player->GetVideoWidth(), player->GetVideoHeight(),
player->GetDuration().InMilliseconds(), player->can_pause(),
player->can_seek_forward(), player->can_seek_backward());
}
} // namespace content

@ -13,73 +13,64 @@
#include "base/memory/scoped_ptr.h"
#include "base/timer.h"
namespace webkit_media {
struct MediaMetadataAndroid;
}
namespace content {
class MediaPlayerDelegateAndroid;
class MediaPlayerManagerAndroid;
// Native mirror of ContentVideoView.java.
// Native mirror of ContentVideoView.java. This class is responsible for
// creating the Java video view and pass all the player status change to
// it. It accepts media control from Java class, and forwards it to
// MediaPlayerManagerAndroid.
class ContentVideoView {
public:
ContentVideoView();
// Construct a ContentVideoView object. The |manager| will handle all the
// playback controls from the Java class.
explicit ContentVideoView(MediaPlayerManagerAndroid* manager);
~ContentVideoView();
static bool RegisterContentVideoView(JNIEnv* env);
void Init(JNIEnv*, jobject obj, jobject weak_this);
// --------------------------------------------------------------------------
// All these functions are called on UI thread
// Getter method called by the Java class to get the media information.
int GetVideoWidth(JNIEnv*, jobject obj) const;
int GetVideoHeight(JNIEnv*, jobject obj) const;
int GetDurationInMilliSeconds(JNIEnv*, jobject obj) const;
int GetCurrentPosition(JNIEnv*, jobject obj) const;
bool IsPlaying(JNIEnv*, jobject obj);
void UpdateMediaMetadata(JNIEnv*, jobject obj);
// Method to create and destroy the Java view.
void DestroyContentVideoView();
void CreateContentVideoView();
// Called when the Java fullscreen view is destroyed. If
// |release_media_player| is true, |manager_| needs to release the player
// as we are quitting the app.
void ExitFullscreen(JNIEnv*, jobject, jboolean release_media_player);
// Media control method called by the Java class.
void SeekTo(JNIEnv*, jobject obj, jint msec);
int GetPlayerId(JNIEnv*, jobject obj) const;
int GetRouteId(JNIEnv*, jobject obj) const;
int GetRenderHandle(JNIEnv*, jobject obj) const;
void Play(JNIEnv*, jobject obj);
void Pause(JNIEnv*, jobject obj);
// --------------------------------------------------------------------------
void PrepareAsync();
void DestroyContentVideoView();
void UpdateMediaMetadata(JNIEnv*, jobject obj);
void DestroyContentVideoView(JNIEnv*, jobject);
void DestroyContentVideoView(JNIEnv*, jobject, jboolean release_media_player);
void CreateContentVideoView(MediaPlayerDelegateAndroid* player);
void SetSurface(JNIEnv*,
jobject obj,
jobject surface,
jint route_id,
jint player_id);
// Called by the Java class to pass the surface object to the player.
void SetSurface(JNIEnv*, jobject obj, jobject surface);
// Method called by |manager_| to inform the Java class about player status
// change.
void UpdateMediaMetadata();
void OnMediaPlayerError(int errorType);
void OnVideoSizeChanged(int width, int height);
void OnBufferingUpdate(int percent);
void OnPlaybackComplete();
private:
// In some certain cases if the renderer crashes, the ExitFullscreen message
// will never acknowledged by the renderer.
void OnTimeout();
webkit_media::MediaMetadataAndroid* GetMediaMetadata();
int ConvertSecondsToMilliSeconds(float seconds) const;
MediaPlayerDelegateAndroid* player_;
// Object that manages the fullscreen media player. It is responsible for
// handling all the playback controls.
MediaPlayerManagerAndroid* manager_;
// Reference to the Java object.
base::android::ScopedJavaGlobalRef<jobject> j_content_video_view_;
// A timer to keep track of when the acknowledgement of exitfullscreen
// message times out.
base::OneShotTimer<ContentVideoView> timeout_timer_;
DISALLOW_COPY_AND_ASSIGN(ContentVideoView);
};

@ -6,7 +6,7 @@
#include "base/bind.h"
#include "content/browser/android/cookie_getter_impl.h"
#include "content/common/view_messages.h"
#include "content/common/media/media_player_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@ -22,7 +22,9 @@ namespace content {
MediaPlayerManagerAndroid::MediaPlayerManagerAndroid(
RenderViewHost* render_view_host)
: RenderViewHostObserver(render_view_host) {
: RenderViewHostObserver(render_view_host),
ALLOW_THIS_IN_INITIALIZER_LIST(video_view_(this)),
fullscreen_player_id_(-1) {
}
MediaPlayerManagerAndroid::~MediaPlayerManagerAndroid() {}
@ -30,25 +32,61 @@ MediaPlayerManagerAndroid::~MediaPlayerManagerAndroid() {}
bool MediaPlayerManagerAndroid::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MediaPlayerManagerAndroid, msg)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayerInitialize,
OnInitialize)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayerStart,
OnStart)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayerSeek,
OnSeek)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayerPause,
OnPause)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayerRelease,
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen, OnEnterFullscreen)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen, OnExitFullscreen)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerInitialize, OnInitialize)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerStart, OnStart)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerSeek, OnSeek)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerPause, OnPause)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerRelease,
OnReleaseResources)
IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyMediaPlayer,
OnDestroyPlayer)
IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyAllMediaPlayers,
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
DestroyAllMediaPlayers)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void MediaPlayerManagerAndroid::FullscreenPlayerPlay() {
MediaPlayerBridge* player = GetFullscreenPlayer();
player->Start();
Send(new MediaPlayerMsg_DidMediaPlayerPlay(
routing_id(), fullscreen_player_id_));
}
void MediaPlayerManagerAndroid::FullscreenPlayerPause() {
MediaPlayerBridge* player = GetFullscreenPlayer();
player->Pause();
Send(new MediaPlayerMsg_DidMediaPlayerPause(
routing_id(), fullscreen_player_id_));
}
void MediaPlayerManagerAndroid::FullscreenPlayerSeek(int msec) {
MediaPlayerBridge* player = GetFullscreenPlayer();
player->SeekTo(base::TimeDelta::FromMilliseconds(msec));
}
void MediaPlayerManagerAndroid::ExitFullscreen(bool release_media_player) {
Send(new MediaPlayerMsg_DidExitFullscreen(
routing_id(), fullscreen_player_id_));
MediaPlayerBridge* player = GetFullscreenPlayer();
if (release_media_player)
player->Release();
else
player->SetVideoSurface(NULL);
fullscreen_player_id_ = -1;
}
void MediaPlayerManagerAndroid::SetVideoSurface(jobject surface) {
MediaPlayerBridge* player = GetFullscreenPlayer();
if (player) {
player->SetVideoSurface(surface);
Send(new MediaPlayerMsg_DidEnterFullscreen(
routing_id(), player->player_id()));
}
}
void MediaPlayerManagerAndroid::OnInitialize(
int player_id, const std::string& url,
const std::string& first_party_for_cookies) {
@ -81,8 +119,8 @@ void MediaPlayerManagerAndroid::OnInitialize(
base::Unretained(this))));
// Send a MediaPrepared message to webkit so that Load() can finish.
Send(new ViewMsg_MediaPrepared(routing_id(), player_id,
GetPlayer(player_id)->GetDuration()));
Send(new MediaPlayerMsg_MediaPrepared(
routing_id(), player_id, GetPlayer(player_id)->GetDuration()));
}
void MediaPlayerManagerAndroid::OnStart(int player_id) {
@ -103,6 +141,23 @@ void MediaPlayerManagerAndroid::OnPause(int player_id) {
player->Pause();
}
void MediaPlayerManagerAndroid::OnEnterFullscreen(int player_id) {
DCHECK_EQ(fullscreen_player_id_, -1);
fullscreen_player_id_ = player_id;
video_view_.CreateContentVideoView();
}
void MediaPlayerManagerAndroid::OnExitFullscreen(int player_id) {
if (fullscreen_player_id_ == player_id) {
MediaPlayerBridge* player = GetPlayer(player_id);
if (player)
player->SetVideoSurface(NULL);
video_view_.DestroyContentVideoView();
fullscreen_player_id_ = -1;
}
}
void MediaPlayerManagerAndroid::OnReleaseResources(int player_id) {
MediaPlayerBridge* player = GetPlayer(player_id);
if (player)
@ -117,10 +172,16 @@ void MediaPlayerManagerAndroid::OnDestroyPlayer(int player_id) {
break;
}
}
if (fullscreen_player_id_ == player_id)
fullscreen_player_id_ = -1;
}
void MediaPlayerManagerAndroid::DestroyAllMediaPlayers() {
players_.clear();
if (fullscreen_player_id_ != -1) {
video_view_.DestroyContentVideoView();
fullscreen_player_id_ = -1;
}
}
MediaPlayerBridge* MediaPlayerManagerAndroid::GetPlayer(int player_id) {
@ -132,38 +193,55 @@ MediaPlayerBridge* MediaPlayerManagerAndroid::GetPlayer(int player_id) {
return NULL;
}
MediaPlayerBridge* MediaPlayerManagerAndroid::GetFullscreenPlayer() {
return GetPlayer(fullscreen_player_id_);
}
void MediaPlayerManagerAndroid::OnPrepared(int player_id,
base::TimeDelta duration) {
Send(new ViewMsg_MediaPrepared(routing_id(), player_id, duration));
Send(new MediaPlayerMsg_MediaPrepared(routing_id(), player_id, duration));
if (fullscreen_player_id_ != -1)
video_view_.UpdateMediaMetadata();
}
void MediaPlayerManagerAndroid::OnPlaybackComplete(int player_id) {
Send(new ViewMsg_MediaPlaybackCompleted(routing_id(), player_id));
Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
if (fullscreen_player_id_ != -1)
video_view_.OnPlaybackComplete();
}
void MediaPlayerManagerAndroid::OnBufferingUpdate(
int player_id, int percentage) {
Send(new ViewMsg_MediaBufferingUpdate(routing_id(), player_id, percentage));
Send(new MediaPlayerMsg_MediaBufferingUpdate(
routing_id(), player_id, percentage));
if (fullscreen_player_id_ != -1)
video_view_.OnBufferingUpdate(percentage);
}
void MediaPlayerManagerAndroid::OnSeekComplete(int player_id,
base::TimeDelta current_time) {
Send(new ViewMsg_MediaSeekCompleted(routing_id(), player_id, current_time));
Send(new MediaPlayerMsg_MediaSeekCompleted(
routing_id(), player_id, current_time));
}
void MediaPlayerManagerAndroid::OnError(int player_id, int error) {
Send(new ViewMsg_MediaError(routing_id(), player_id, error));
Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
if (fullscreen_player_id_ != -1)
video_view_.OnMediaPlayerError(error);
}
void MediaPlayerManagerAndroid::OnVideoSizeChanged(
int player_id, int width, int height) {
Send(new ViewMsg_MediaVideoSizeChanged(routing_id(), player_id,
Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
width, height));
if (fullscreen_player_id_ != -1)
video_view_.OnVideoSizeChanged(width, height);
}
void MediaPlayerManagerAndroid::OnTimeUpdate(int player_id,
base::TimeDelta current_time) {
Send(new ViewMsg_MediaTimeUpdate(routing_id(), player_id, current_time));
Send(new MediaPlayerMsg_MediaTimeUpdate(
routing_id(), player_id, current_time));
}
void MediaPlayerManagerAndroid::RequestMediaResources(
@ -189,9 +267,11 @@ void MediaPlayerManagerAndroid::RequestMediaResources(
return;
for (it = players_.begin(); it != players_.end(); ++it) {
if ((*it)->prepared() && !(*it)->IsPlaying()) {
if ((*it)->prepared() && !(*it)->IsPlaying() &&
fullscreen_player_id_ != (*it)->player_id()) {
(*it)->Release();
Send(new ViewMsg_MediaPlayerReleased(routing_id(), (*it)->player_id()));
Send(new MediaPlayerMsg_MediaPlayerReleased(
routing_id(), (*it)->player_id()));
}
}
}

@ -11,6 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/time.h"
#include "content/browser/android/content_video_view.h"
#include "content/public/browser/render_view_host_observer.h"
#include "media/base/android/media_player_bridge.h"
#include "media/base/android/media_player_bridge_manager.h"
@ -33,6 +34,13 @@ class MediaPlayerManagerAndroid
// RenderViewHostObserver overrides.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// Fullscreen video playback controls.
void FullscreenPlayerPlay();
void FullscreenPlayerPause();
void FullscreenPlayerSeek(int msec);
void ExitFullscreen(bool release_media_player);
void SetVideoSurface(jobject surface);
// An internal method that checks for current time routinely and generates
// time update events.
void OnTimeUpdate(int player_id, base::TimeDelta current_time);
@ -52,10 +60,13 @@ class MediaPlayerManagerAndroid
// Release all the players managed by this object.
void DestroyAllMediaPlayers();
media::MediaPlayerBridge* GetFullscreenPlayer();
media::MediaPlayerBridge* GetPlayer(int player_id);
private:
// Message handlers.
void OnEnterFullscreen(int player_id);
void OnExitFullscreen(int player_id);
void OnInitialize(int player_id, const std::string& url,
const std::string& first_party_for_cookies);
void OnStart(int player_id);
@ -67,6 +78,12 @@ class MediaPlayerManagerAndroid
// An array of managed players.
ScopedVector<media::MediaPlayerBridge> players_;
// The fullscreen video view object.
ContentVideoView video_view_;
// Player ID of the fullscreen media player.
int fullscreen_player_id_;
DISALLOW_COPY_AND_ASSIGN(MediaPlayerManagerAndroid);
};

@ -38,8 +38,9 @@ static void SetSurfacePeer(jobject j_surface,
if (host) {
media::MediaPlayerBridge* player =
host->media_player_manager()->GetPlayer(player_id);
if (player) {
player->SetVideoSurface(j_surface);
if (player &&
player != host->media_player_manager()->GetFullscreenPlayer()) {
player->SetVideoSurface(j_surface);
}
}
}

@ -29,6 +29,7 @@
#include "content/common/intents_messages.h"
#include "content/common/java_bridge_messages.h"
#include "content/common/media/audio_messages.h"
#include "content/common/media/media_player_messages.h"
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/video_capture_messages.h"
#include "content/common/mime_registry_messages.h"

@ -0,0 +1,113 @@
// Copyright (c) 2012 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.
// IPC messages for android media player.
// Multiply-included message file, hence no include guard.
#include <string>
#include "base/time.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START MediaPlayerMsgStart
// Messages for notifying the render process of media playback status -------
// Media buffering has updated.
IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaBufferingUpdate,
int /* player_id */,
int /* percent */)
// A media playback error has occured.
IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaError,
int /* player_id */,
int /* error */)
// Playback is completed.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_MediaPlaybackCompleted,
int /* player_id */)
// Player is prepared.
IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaPrepared,
int /* player_id */,
base::TimeDelta /* duration */)
// Media seek is completed.
IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaSeekCompleted,
int /* player_id */,
base::TimeDelta /* current_time */)
// Video size has changed.
IPC_MESSAGE_ROUTED3(MediaPlayerMsg_MediaVideoSizeChanged,
int /* player_id */,
int /* width */,
int /* height */)
// The current play time has updated.
IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaTimeUpdate,
int /* player_id */,
base::TimeDelta /* current_time */)
// The player has been released.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_MediaPlayerReleased,
int /* player_id */)
// The player has entered fullscreen mode.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DidEnterFullscreen,
int /* player_id */)
// The player exited fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DidExitFullscreen,
int /* player_id */)
// The player started playing.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DidMediaPlayerPlay,
int /* player_id */)
// The player was paused.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DidMediaPlayerPause,
int /* player_id */)
// Messages for controllering the media playback in browser process ----------
// Destroy the media player object.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_DestroyMediaPlayer,
int /* player_id */)
// Destroy all the players.
IPC_MESSAGE_ROUTED0(MediaPlayerHostMsg_DestroyAllMediaPlayers)
// Initialize a media player object with the given player_id.
IPC_MESSAGE_ROUTED3(MediaPlayerHostMsg_MediaPlayerInitialize,
int /* player_id */,
std::string /* url */,
std::string /* first_party_for_cookies */)
// Pause the player.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_MediaPlayerPause,
int /* player_id */)
// Release player resources, but keep the object for future usage.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_MediaPlayerRelease,
int /* player_id */)
// Perform a seek.
IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_MediaPlayerSeek,
int /* player_id */,
base::TimeDelta /* time */)
// Start the player for playback.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_MediaPlayerStart,
int /* player_id */)
// Request the player to enter fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_EnterFullscreen,
int /* player_id */)
// Request the player to exit fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_ExitFullscreen,
int /* player_id */)

@ -54,10 +54,6 @@
#include "content/common/mac/font_descriptor.h"
#endif
#if defined(OS_ANDROID)
#include "webkit/media/android/media_metadata_android.h"
#endif
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@ -380,19 +376,6 @@ IPC_STRUCT_TRAITS_BEGIN(ui::SelectedFileInfo)
IPC_STRUCT_TRAITS_MEMBER(display_name)
IPC_STRUCT_TRAITS_END()
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_BEGIN(webkit_media::MediaMetadataAndroid)
IPC_STRUCT_TRAITS_MEMBER(width)
IPC_STRUCT_TRAITS_MEMBER(height)
IPC_STRUCT_TRAITS_MEMBER(duration)
IPC_STRUCT_TRAITS_MEMBER(current_time)
IPC_STRUCT_TRAITS_MEMBER(paused)
IPC_STRUCT_TRAITS_MEMBER(can_pause)
IPC_STRUCT_TRAITS_MEMBER(can_seek_forward)
IPC_STRUCT_TRAITS_MEMBER(can_seek_backward)
IPC_STRUCT_TRAITS_END()
#endif
IPC_STRUCT_BEGIN(ViewHostMsg_CreateWindow_Params)
// Routing ID of the view initiating the open.
IPC_STRUCT_MEMBER(int, opener_id)
@ -2399,77 +2382,4 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_FindMatchRects_Reply,
// Start an android intent with the given URI.
IPC_MESSAGE_ROUTED1(ViewHostMsg_StartContentIntent,
GURL /* content_url */)
// Messages for notifying the render process of media playback status -------
// Media buffering has updated.
IPC_MESSAGE_ROUTED2(ViewMsg_MediaBufferingUpdate,
int /* player_id */,
int /* percent */)
// A media playback error has occured.
IPC_MESSAGE_ROUTED2(ViewMsg_MediaError,
int /* player_id */,
int /* error */)
// Playback is completed.
IPC_MESSAGE_ROUTED1(ViewMsg_MediaPlaybackCompleted,
int /* player_id */)
// Player is prepared.
IPC_MESSAGE_ROUTED2(ViewMsg_MediaPrepared,
int /* player_id */,
base::TimeDelta /* duration */)
// Media seek is completed.
IPC_MESSAGE_ROUTED2(ViewMsg_MediaSeekCompleted,
int /* player_id */,
base::TimeDelta /* current_time */)
// Video size has changed.
IPC_MESSAGE_ROUTED3(ViewMsg_MediaVideoSizeChanged,
int /* player_id */,
int /* width */,
int /* height */)
// The current play time has updated.
IPC_MESSAGE_ROUTED2(ViewMsg_MediaTimeUpdate,
int /* player_id */,
base::TimeDelta /* current_time */)
// The player has been released.
IPC_MESSAGE_ROUTED1(ViewMsg_MediaPlayerReleased,
int /* player_id */)
// Messages for controllering the media playback in browser process ----------
// Destroy the media player object.
IPC_MESSAGE_ROUTED1(ViewHostMsg_DestroyMediaPlayer,
int /* player_id */)
// Destroy all the players.
IPC_MESSAGE_ROUTED0(ViewHostMsg_DestroyAllMediaPlayers)
// Initialize a media player object with the given player_id.
IPC_MESSAGE_ROUTED3(ViewHostMsg_MediaPlayerInitialize,
int /* player_id */,
std::string /* url */,
std::string /* first_party_for_cookies */)
// Pause the player.
IPC_MESSAGE_ROUTED1(ViewHostMsg_MediaPlayerPause,
int /* player_id */)
// Release player resources, but keep the object for future usage.
IPC_MESSAGE_ROUTED1(ViewHostMsg_MediaPlayerRelease,
int /* player_id */)
// Perform a seek.
IPC_MESSAGE_ROUTED2(ViewHostMsg_MediaPlayerSeek,
int /* player_id */,
base::TimeDelta /* time */)
// Start the player for playback.
IPC_MESSAGE_ROUTED1(ViewHostMsg_MediaPlayerStart,
int /* player_id */)
#endif

@ -288,6 +288,7 @@
'common/media/audio_messages.h',
'common/media/audio_param_traits.cc',
'common/media/audio_param_traits.h',
'common/media/media_player_messages.h',
'common/media/media_stream_messages.h',
'common/media/media_stream_options.cc',
'common/media/media_stream_options.h',

@ -88,7 +88,6 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
private boolean mCanPause;
private boolean mCanSeekBack;
private boolean mCanSeekForward;
private boolean mHasMediaMetadata = false;
// Native pointer to C++ ContentVideoView object.
private int mNativeContentVideoView = 0;
@ -103,14 +102,11 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
static String mErrorTitle;
// This view will contain the video.
private static VideoSurfaceView sVideoSurfaceView;
private VideoSurfaceView mVideoSurfaceView;
private Surface mSurface = null;
private static Activity sChromeActivity;
private static FrameLayout sRootLayout;
private static ViewGroup sContentContainer;
private static ViewGroup sControlContainer;
// There are can be at most 1 fullscreen video
// TODO(qinmin): will change this once we move the creation of this class
@ -138,6 +134,13 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
}
}
private Runnable mExitFullscreenRunnable = new Runnable() {
@Override
public void run() {
destroyContentVideoView();
}
};
public ContentVideoView(Context context) {
this(context, 0);
}
@ -150,7 +153,7 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
mNativeContentVideoView = nativeContentVideoView;
mCurrentBufferPercentage = 0;
sVideoSurfaceView = new VideoSurfaceView(context);
mVideoSurfaceView = new VideoSurfaceView(context);
mCurrentState = isPlaying() ? STATE_PLAYING : STATE_PAUSED;
}
@ -171,18 +174,19 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
}
void showContentVideoView() {
this.addView(sVideoSurfaceView,
this.addView(mVideoSurfaceView,
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.CENTER));
sVideoSurfaceView.setOnKeyListener(this);
sVideoSurfaceView.setOnTouchListener(this);
sVideoSurfaceView.getHolder().addCallback(this);
sVideoSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
sVideoSurfaceView.setFocusable(true);
sVideoSurfaceView.setFocusableInTouchMode(true);
sVideoSurfaceView.requestFocus();
mVideoSurfaceView.setZOrderMediaOverlay(true);
mVideoSurfaceView.setOnKeyListener(this);
mVideoSurfaceView.setOnTouchListener(this);
mVideoSurfaceView.getHolder().addCallback(this);
mVideoSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mVideoSurfaceView.setFocusable(true);
mVideoSurfaceView.setFocusableInTouchMode(true);
mVideoSurfaceView.requestFocus();
}
@CalledByNative
@ -235,7 +239,7 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
mVideoWidth = width;
mVideoHeight = height;
if (mVideoWidth != 0 && mVideoHeight != 0) {
sVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
}
}
@ -261,7 +265,6 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
mCanPause = canPause;
mCanSeekBack = canSeekBack;
mCanSeekForward = canSeekForward;
mHasMediaMetadata = true;
if (mMediaController != null) {
mMediaController.setEnabled(true);
@ -278,19 +281,19 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
public void destroyNativeView() {
if (mNativeContentVideoView != 0) {
mNativeContentVideoView = 0;
destroyContentVideoView();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
sVideoSurfaceView.setFocusable(true);
sVideoSurfaceView.setFocusableInTouchMode(true);
mVideoSurfaceView.setFocusable(true);
mVideoSurfaceView.setFocusableInTouchMode(true);
if (isInPlaybackState() && mMediaController != null) {
if (mMediaController.isShowing()) {
// ensure the controller will get repositioned later
mMediaController.hide();
}
mMediaController.show();
}
}
@ -304,13 +307,11 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
public void surfaceDestroyed(SurfaceHolder holder) {
mSurfaceHolder = null;
if (mNativeContentVideoView != 0) {
nativeDestroyContentVideoView(mNativeContentVideoView, true);
destroyNativeView();
}
if (mMediaController != null) {
mMediaController.hide();
mMediaController = null;
nativeExitFullscreen(mNativeContentVideoView, true);
mNativeContentVideoView = 0;
post(mExitFullscreenRunnable);
}
removeMediaController();
}
public void setMediaController(MediaController controller) {
@ -324,8 +325,8 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
private void attachMediaController() {
if (mMediaController != null) {
mMediaController.setMediaPlayer(this);
mMediaController.setAnchorView(sVideoSurfaceView);
mMediaController.setEnabled(mHasMediaMetadata);
mMediaController.setAnchorView(mVideoSurfaceView);
mMediaController.setEnabled(true);
}
}
@ -337,38 +338,12 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
}
mCurrentBufferPercentage = 0;
if (mNativeContentVideoView != 0) {
int renderHandle = nativeGetRenderHandle(mNativeContentVideoView);
if (renderHandle == 0) {
nativeSetSurface(mNativeContentVideoView,
mSurfaceHolder.getSurface(),
nativeGetRouteId(mNativeContentVideoView),
nativeGetPlayerId(mNativeContentVideoView));
return;
}
ISandboxedProcessService service =
SandboxedProcessLauncher.getSandboxedService(renderHandle);
if (service == null) {
Log.e(TAG, "Unable to get SandboxedProcessService from pid.");
return;
}
try {
service.setSurface(
SET_VIDEO_SURFACE_TEXTURE,
mSurfaceHolder.getSurface(),
nativeGetRouteId(mNativeContentVideoView),
nativeGetPlayerId(mNativeContentVideoView));
} catch (RemoteException e) {
Log.e(TAG, "Unable to call setSurfaceTexture: " + e);
return;
}
nativeSetSurface(mNativeContentVideoView,
mSurfaceHolder.getSurface());
}
requestLayout();
invalidate();
setMediaController(new MediaController(getChromeActivity()));
if (mMediaController != null) {
mMediaController.show();
}
}
}
@ -435,7 +410,7 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
}
} else if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
if (mNativeContentVideoView != 0) {
nativeDestroyContentVideoView(mNativeContentVideoView, false);
nativeExitFullscreen(mNativeContentVideoView, false);
destroyNativeView();
}
return true;
@ -530,32 +505,27 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
@CalledByNative
public static ContentVideoView createContentVideoView(int nativeContentVideoView) {
if (sContentVideoView != null)
return sContentVideoView;
if (getChromeActivity() != null) {
ContentVideoView videoView = new ContentVideoView(getChromeActivity(),
sContentVideoView = new ContentVideoView(getChromeActivity(),
nativeContentVideoView);
if (sContentVideoView != null) {
return videoView;
}
sContentVideoView = videoView;
sContentContainer.setVisibility(View.GONE);
sControlContainer.setVisibility(View.GONE);
sChromeActivity.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
sChromeActivity.getWindow().addContentView(videoView,
sChromeActivity.getWindow().addContentView(sContentVideoView,
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
Gravity.CENTER));
videoView.setBackgroundColor(Color.BLACK);
sContentVideoView.setBackgroundColor(Color.BLACK);
sContentVideoView.showContentVideoView();
videoView.setVisibility(View.VISIBLE);
return videoView;
sContentVideoView.setVisibility(View.VISIBLE);
return sContentVideoView;
}
return null;
}
@ -564,23 +534,27 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
return sChromeActivity;
}
public static void showFullScreen(ContentVideoView fullscreenView) {
public void removeMediaController() {
if (mMediaController != null) {
mMediaController.setEnabled(false);
mMediaController.hide();
mMediaController = null;
}
}
public void removeSurfaceView() {
removeView(mVideoSurfaceView);
mVideoSurfaceView = null;
}
@CalledByNative
public static void destroyContentVideoView() {
sChromeActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (sContentVideoView != null) {
sContentVideoView.removeView(sVideoSurfaceView);
sVideoSurfaceView = null;
sContentVideoView.removeMediaController();
sContentVideoView.removeSurfaceView();
sContentVideoView.setVisibility(View.GONE);
sRootLayout.removeView(sContentVideoView);
}
sContentContainer.setVisibility(View.VISIBLE);
sControlContainer.setVisibility(View.VISIBLE);
sContentVideoView = null;
}
@ -588,17 +562,13 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
return sContentVideoView;
}
public static void registerChromeActivity(Activity activity, FrameLayout rootLayout,
ViewGroup controlContainer, ViewGroup contentContainer) {
public static void registerChromeActivity(Activity activity) {
sChromeActivity = activity;
sRootLayout = rootLayout;
sControlContainer = controlContainer;
sContentContainer = contentContainer;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return false;
return true;
}
@Override
@ -610,20 +580,15 @@ public class ContentVideoView extends FrameLayout implements MediaPlayerControl,
return super.onKeyDown(keyCode, event);
}
private native void nativeDestroyContentVideoView(int nativeContentVideoView,
boolean relaseMediaPlayer);
private native void nativeExitFullscreen(int nativeContentVideoView, boolean relaseMediaPlayer);
private native int nativeGetCurrentPosition(int nativeContentVideoView);
private native int nativeGetDurationInMilliSeconds(int nativeContentVideoView);
private native void nativeUpdateMediaMetadata(int nativeContentVideoView);
private native int nativeGetVideoWidth(int nativeContentVideoView);
private native int nativeGetVideoHeight(int nativeContentVideoView);
private native int nativeGetPlayerId(int nativeContentVideoView);
private native int nativeGetRouteId(int nativeContentVideoView);
private native int nativeGetRenderHandle(int nativeContentVideoView);
private native boolean nativeIsPlaying(int nativeContentVideoView);
private native void nativePause(int nativeContentVideoView);
private native void nativePlay(int nativeContentVideoView);
private native void nativeSeekTo(int nativeContentVideoView, int msec);
private native void nativeSetSurface(int nativeContentVideoView,
Surface surface, int routeId, int playerId);
private native void nativeSetSurface(int nativeContentVideoView, Surface surface);
}

@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/message_loop.h"
#include "content/common/view_messages.h"
#include "content/common/media/media_player_messages.h"
#include "webkit/media/android/webmediaplayer_impl_android.h"
#include "webkit/media/android/webmediaplayer_manager_android.h"
@ -20,22 +20,29 @@ WebMediaPlayerProxyImplAndroid::WebMediaPlayerProxyImplAndroid(
}
WebMediaPlayerProxyImplAndroid::~WebMediaPlayerProxyImplAndroid() {
Send(new ViewHostMsg_DestroyAllMediaPlayers(routing_id()));
Send(new MediaPlayerHostMsg_DestroyAllMediaPlayers(routing_id()));
}
bool WebMediaPlayerProxyImplAndroid::OnMessageReceived(
const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebMediaPlayerProxyImplAndroid, msg)
IPC_MESSAGE_HANDLER(ViewMsg_MediaPrepared, OnMediaPrepared)
IPC_MESSAGE_HANDLER(ViewMsg_MediaPlaybackCompleted,
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPrepared, OnMediaPrepared)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlaybackCompleted,
OnMediaPlaybackCompleted)
IPC_MESSAGE_HANDLER(ViewMsg_MediaBufferingUpdate, OnMediaBufferingUpdate)
IPC_MESSAGE_HANDLER(ViewMsg_MediaSeekCompleted, OnMediaSeekCompleted)
IPC_MESSAGE_HANDLER(ViewMsg_MediaError, OnMediaError)
IPC_MESSAGE_HANDLER(ViewMsg_MediaVideoSizeChanged, OnVideoSizeChanged)
IPC_MESSAGE_HANDLER(ViewMsg_MediaTimeUpdate, OnTimeUpdate)
IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerReleased, OnMediaPlayerReleased)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaBufferingUpdate,
OnMediaBufferingUpdate)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaSeekCompleted, OnMediaSeekCompleted)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaError, OnMediaError)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaVideoSizeChanged,
OnVideoSizeChanged)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaTimeUpdate, OnTimeUpdate)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlayerReleased,
OnMediaPlayerReleased)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidEnterFullscreen, OnDidEnterFullscreen)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@ -44,28 +51,28 @@ bool WebMediaPlayerProxyImplAndroid::OnMessageReceived(
void WebMediaPlayerProxyImplAndroid::Initialize(
int player_id, const std::string& url,
const std::string& first_party_for_cookies) {
Send(new ViewHostMsg_MediaPlayerInitialize(
Send(new MediaPlayerHostMsg_MediaPlayerInitialize(
routing_id(), player_id, url, first_party_for_cookies));
}
void WebMediaPlayerProxyImplAndroid::Start(int player_id) {
Send(new ViewHostMsg_MediaPlayerStart(routing_id(), player_id));
Send(new MediaPlayerHostMsg_MediaPlayerStart(routing_id(), player_id));
}
void WebMediaPlayerProxyImplAndroid::Pause(int player_id) {
Send(new ViewHostMsg_MediaPlayerPause(routing_id(), player_id));
Send(new MediaPlayerHostMsg_MediaPlayerPause(routing_id(), player_id));
}
void WebMediaPlayerProxyImplAndroid::Seek(int player_id, base::TimeDelta time) {
Send(new ViewHostMsg_MediaPlayerSeek(routing_id(), player_id, time));
Send(new MediaPlayerHostMsg_MediaPlayerSeek(routing_id(), player_id, time));
}
void WebMediaPlayerProxyImplAndroid::ReleaseResources(int player_id) {
Send(new ViewHostMsg_MediaPlayerRelease(routing_id(), player_id));
Send(new MediaPlayerHostMsg_MediaPlayerRelease(routing_id(), player_id));
}
void WebMediaPlayerProxyImplAndroid::DestroyPlayer(int player_id) {
Send(new ViewHostMsg_DestroyMediaPlayer(routing_id(), player_id));
Send(new MediaPlayerHostMsg_DestroyMediaPlayer(routing_id(), player_id));
}
void WebMediaPlayerProxyImplAndroid::OnMediaPrepared(
@ -133,6 +140,44 @@ void WebMediaPlayerProxyImplAndroid::OnMediaPlayerReleased(
player->OnPlayerReleased();
}
void WebMediaPlayerProxyImplAndroid::OnDidEnterFullscreen(
int player_id) {
webkit_media::WebMediaPlayerImplAndroid* player =
GetWebMediaPlayer(player_id);
if (player)
player->OnDidEnterFullscreen();
}
void WebMediaPlayerProxyImplAndroid::OnDidExitFullscreen(
int player_id) {
webkit_media::WebMediaPlayerImplAndroid* player =
GetWebMediaPlayer(player_id);
if (player)
player->OnDidExitFullscreen();
}
void WebMediaPlayerProxyImplAndroid::OnPlayerPlay(int player_id) {
webkit_media::WebMediaPlayerImplAndroid* player =
GetWebMediaPlayer(player_id);
if (player)
player->OnMediaPlayerPlay();
}
void WebMediaPlayerProxyImplAndroid::OnPlayerPause(int player_id) {
webkit_media::WebMediaPlayerImplAndroid* player =
GetWebMediaPlayer(player_id);
if (player)
player->OnMediaPlayerPause();
}
void WebMediaPlayerProxyImplAndroid::EnterFullscreen(int player_id) {
Send(new MediaPlayerHostMsg_EnterFullscreen(routing_id(), player_id));
}
void WebMediaPlayerProxyImplAndroid::ExitFullscreen(int player_id) {
Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id));
}
webkit_media::WebMediaPlayerImplAndroid*
WebMediaPlayerProxyImplAndroid::GetWebMediaPlayer(int player_id) {
return static_cast<webkit_media::WebMediaPlayerImplAndroid*>(

@ -42,6 +42,8 @@ class WebMediaPlayerProxyImplAndroid
virtual void Seek(int player_id, base::TimeDelta time) OVERRIDE;
virtual void ReleaseResources(int player_id) OVERRIDE;
virtual void DestroyPlayer(int player_id) OVERRIDE;
virtual void EnterFullscreen(int player_id) OVERRIDE;
virtual void ExitFullscreen(int player_id) OVERRIDE;
private:
webkit_media::WebMediaPlayerImplAndroid* GetWebMediaPlayer(int player_id);
@ -55,6 +57,10 @@ class WebMediaPlayerProxyImplAndroid
void OnVideoSizeChanged(int player_id, int width, int height);
void OnTimeUpdate(int player_id, base::TimeDelta current_time);
void OnMediaPlayerReleased(int player_id);
void OnDidExitFullscreen(int player_id);
void OnDidEnterFullscreen(int player_id);
void OnPlayerPlay(int player_id);
void OnPlayerPause(int player_id);
webkit_media::WebMediaPlayerManagerAndroid* manager_;

@ -108,6 +108,7 @@ enum IPCMessageStart {
AndroidWebViewMsgStart,
MetroViewerMsgStart,
CCMsgStart,
MediaPlayerMsgStart,
LastIPCMsgStart // Must come last.
};

@ -172,7 +172,6 @@ void MediaPlayerBridge::Pause() {
}
}
bool MediaPlayerBridge::IsPlaying() {
if (!prepared_)
return pending_play_;

@ -72,7 +72,7 @@ class MediaPlayerBridge {
MediaPlayerBridge(int player_id,
const std::string& url,
const std::string& first_party_for_cookies,
CookieGetter* cookies_getter,
CookieGetter* cookie_getter,
bool hide_url_log,
MediaPlayerBridgeManager* manager,
const MediaErrorCB& media_error_cb,

@ -1,39 +0,0 @@
// Copyright (c) 2012 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 "webkit/media/android/media_metadata_android.h"
namespace webkit_media {
MediaMetadataAndroid::MediaMetadataAndroid()
: width(0),
height(0),
paused(false),
can_pause(false),
can_seek_forward(false),
can_seek_backward(false) {
}
MediaMetadataAndroid::MediaMetadataAndroid(int w,
int h,
base::TimeDelta d,
base::TimeDelta ct,
bool p,
bool cp,
bool csf,
bool csb)
: width(w),
height(h),
duration(d),
current_time(ct),
paused(p),
can_pause(cp),
can_seek_forward(csf),
can_seek_backward(csb) {
}
MediaMetadataAndroid::~MediaMetadataAndroid() {
}
} // namespace webkit_media

@ -1,38 +0,0 @@
// Copyright (c) 2012 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.
#ifndef WEBKIT_MEDIA_ANDROID_MEDIA_METADATA_ANDROID_H_
#define WEBKIT_MEDIA_ANDROID_MEDIA_METADATA_ANDROID_H_
#include "base/basictypes.h"
#include "base/time.h"
namespace webkit_media {
// Provides the initial media metadata to ContentVideoView.
struct MediaMetadataAndroid {
MediaMetadataAndroid();
MediaMetadataAndroid(int w,
int h,
base::TimeDelta d,
base::TimeDelta ct,
bool p,
bool cp,
bool csf,
bool csb);
~MediaMetadataAndroid();
int width;
int height;
base::TimeDelta duration;
base::TimeDelta current_time;
bool paused;
bool can_pause;
bool can_seek_forward;
bool can_seek_backward;
};
} // namespace webkit_media
#endif // WEBKIT_MEDIA_ANDROID_MEDIA_METADATA_ANDROID_H_

@ -410,6 +410,10 @@ void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() {
needs_establish_peer_ = false;
}
void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) {
needs_establish_peer_ = needs_establish_peer;
}
void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
is_playing_ = is_playing;
}

@ -137,9 +137,12 @@ class WebMediaPlayerAndroid
virtual void UpdateReadyState(WebKit::WebMediaPlayer::ReadyState state);
// Helper method to reestablish the surface texture peer for android
// mediaplayer.
// media player.
virtual void EstablishSurfaceTexturePeer();
// Requesting whether the surface texture peer needs to be reestablished.
virtual void SetNeedsEstablishPeer(bool needs_establish_peer);
// Method to be implemented by child classes.
// Initialize the media player bridge object.
virtual void InitializeMediaPlayer(GURL url) = 0;
@ -164,7 +167,9 @@ class WebMediaPlayerAndroid
WebKit::WebMediaPlayerClient* client() { return client_; }
int player_id() { return player_id_; }
int player_id() const { return player_id_; }
WebMediaPlayerManagerAndroid* manager() const { return manager_; }
private:
WebKit::WebMediaPlayerClient* const client_;

@ -8,8 +8,10 @@
#include "base/logging.h"
#include "media/base/android/media_player_bridge.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "webkit/media/android/stream_texture_factory_android.h"
#include "webkit/media/android/webmediaplayer_manager_android.h"
#include "webkit/media/android/webmediaplayer_proxy_android.h"
@ -35,10 +37,28 @@ WebMediaPlayerImplAndroid::~WebMediaPlayerImplAndroid() {
Destroy();
}
void WebMediaPlayerImplAndroid::enterFullscreen() {
if (proxy_ && manager()->CanEnterFullscreen(frame_)) {
proxy_->EnterFullscreen(player_id());
SetNeedsEstablishPeer(false);
}
}
void WebMediaPlayerImplAndroid::exitFullscreen() {
if (proxy_)
proxy_->ExitFullscreen(player_id());
}
bool WebMediaPlayerImplAndroid::canEnterFullscreen() const {
return manager()->CanEnterFullscreen(frame_);
}
void WebMediaPlayerImplAndroid::InitializeMediaPlayer(GURL url) {
GURL first_party_url = frame_->document().firstPartyForCookies();
if (proxy_) {
proxy_->Initialize(player_id(), url.spec(), first_party_url.spec());
if (manager()->IsInFullscreen(frame_))
proxy_->EnterFullscreen(player_id());
}
UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
@ -73,6 +93,37 @@ void WebMediaPlayerImplAndroid::OnTimeUpdate(base::TimeDelta current_time) {
current_time_ = static_cast<float>(current_time.InSecondsF());
}
void WebMediaPlayerImplAndroid::OnDidEnterFullscreen() {
if (!manager()->IsInFullscreen(frame_)) {
frame_->view()->willEnterFullScreen();
frame_->view()->didEnterFullScreen();
manager()->DidEnterFullscreen(frame_);
}
}
void WebMediaPlayerImplAndroid::OnDidExitFullscreen() {
SetNeedsEstablishPeer(true);
// We had the fullscreen surface connected to Android MediaPlayer,
// so reconnect our surface texture for embedded playback.
if (!paused())
EstablishSurfaceTexturePeer();
frame_->view()->willExitFullScreen();
frame_->view()->didExitFullScreen();
manager()->DidExitFullscreen();
client()->repaint();
}
void WebMediaPlayerImplAndroid::OnMediaPlayerPlay() {
UpdatePlayingState(true);
client()->playbackStateChanged();
}
void WebMediaPlayerImplAndroid::OnMediaPlayerPause() {
UpdatePlayingState(false);
client()->playbackStateChanged();
}
void WebMediaPlayerImplAndroid::Destroy() {
proxy_->DestroyPlayer(player_id());
proxy_ = NULL;

@ -45,6 +45,17 @@ class WebMediaPlayerImplAndroid : public WebMediaPlayerAndroid {
StreamTextureFactory* factory);
virtual ~WebMediaPlayerImplAndroid();
// WebKit::WebMediaPlayer implementation.
virtual void enterFullscreen();
virtual void exitFullscreen();
virtual bool canEnterFullscreen() const;
// Functions called when media player status changes.
void OnMediaPlayerPlay();
void OnMediaPlayerPause();
void OnDidEnterFullscreen();
void OnDidExitFullscreen();
// WebMediaPlayerAndroid implementation.
virtual void OnTimeUpdate(base::TimeDelta current_time) OVERRIDE;
virtual void SetVideoSurface(jobject j_surface) OVERRIDE;

@ -9,11 +9,11 @@
namespace webkit_media {
WebMediaPlayerManagerAndroid::WebMediaPlayerManagerAndroid()
: next_media_player_id_(0) {
: next_media_player_id_(0),
fullscreen_frame_(NULL) {
}
WebMediaPlayerManagerAndroid::~WebMediaPlayerManagerAndroid() {
ReleaseMediaResources();
}
int WebMediaPlayerManagerAndroid::RegisterMediaPlayer(
@ -43,4 +43,20 @@ WebMediaPlayerAndroid* WebMediaPlayerManagerAndroid::GetMediaPlayer(
return NULL;
}
bool WebMediaPlayerManagerAndroid::CanEnterFullscreen(WebKit::WebFrame* frame) {
return !fullscreen_frame_ || IsInFullscreen(frame);
}
void WebMediaPlayerManagerAndroid::DidEnterFullscreen(WebKit::WebFrame* frame) {
fullscreen_frame_ = frame;
}
void WebMediaPlayerManagerAndroid::DidExitFullscreen() {
fullscreen_frame_ = NULL;
}
bool WebMediaPlayerManagerAndroid::IsInFullscreen(WebKit::WebFrame* frame) {
return fullscreen_frame_ == frame;
}
} // namespace webkit_media

@ -9,6 +9,10 @@
#include "base/basictypes.h"
namespace WebKit {
class WebFrame;
}
namespace webkit_media {
class WebMediaPlayerAndroid;
@ -27,6 +31,16 @@ class WebMediaPlayerManagerAndroid {
// Release all the media resources managed by this object.
void ReleaseMediaResources();
// Check whether a player can enter fullscreen.
bool CanEnterFullscreen(WebKit::WebFrame* frame);
// Called when a player entered or exited fullscreen.
void DidEnterFullscreen(WebKit::WebFrame* frame);
void DidExitFullscreen();
// Check whether the Webframe is in fullscreen.
bool IsInFullscreen(WebKit::WebFrame* frame);
// Get the pointer to WebMediaPlayerAndroid given the |player_id|.
WebMediaPlayerAndroid* GetMediaPlayer(int player_id);
@ -37,6 +51,9 @@ class WebMediaPlayerManagerAndroid {
int32 next_media_player_id_;
// WebFrame of the fullscreen video.
WebKit::WebFrame* fullscreen_frame_;
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerManagerAndroid);
};

@ -37,6 +37,12 @@ class WebMediaPlayerProxyAndroid {
// Destroy the player in the browser process
virtual void DestroyPlayer(int player_id) = 0;
// Request the player to enter fullscreen.
virtual void EnterFullscreen(int player_id) = 0;
// Request the player to exit fullscreen.
virtual void ExitFullscreen(int player_id) = 0;
};
} // namespace webkit_media

@ -16,8 +16,6 @@
],
'sources': [
'android/audio_decoder_android.cc',
'android/media_metadata_android.cc',
'android/media_metadata_android.h',
'android/media_player_bridge_manager_impl.cc',
'android/media_player_bridge_manager_impl.h',
'android/stream_texture_factory_android.h',