Commit 480c0347 authored by wonsik@chromium.org's avatar wonsik@chromium.org

Location/size change notification when external rendering is enabled

Extract location/size of the video at renderer process and
pass it to browser process where the external surface
resides, so that app can readjust the location of external
surface when it is changed.

BUG=180197
R=scherkus@chromium.org,yfriedman@chromium.org,sky@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195148 0039d316-1c4b-4281-b951-d872f2087c98
parent c39ee69e
......@@ -611,6 +611,23 @@ void ContentViewCoreImpl::RequestExternalVideoSurface(int player_id) {
env, obj.obj(), static_cast<jint>(player_id));
}
void ContentViewCoreImpl::NotifyGeometryChange(int player_id,
const gfx::RectF& rect) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
Java_ContentViewCore_notifyGeometryChange(env,
obj.obj(),
static_cast<jint>(player_id),
static_cast<jfloat>(rect.x()),
static_cast<jfloat>(rect.y()),
static_cast<jfloat>(rect.width()),
static_cast<jfloat>(rect.height()));
}
gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
......@@ -1223,23 +1240,27 @@ void ContentViewCoreImpl::AttachExternalVideoSurface(JNIEnv* env,
jobject obj,
jint player_id,
jobject jsurface) {
#if defined(GOOGLE_TV)
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
web_contents_->GetRenderViewHost());
if (rvhi && rvhi->media_player_manager()) {
rvhi->media_player_manager()->AttachExternalVideoSurface(
static_cast<int>(player_id), jsurface);
}
#endif
}
void ContentViewCoreImpl::DetachExternalVideoSurface(JNIEnv* env,
jobject obj,
jint player_id) {
#if defined(GOOGLE_TV)
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
web_contents_->GetRenderViewHost());
if (rvhi && rvhi->media_player_manager()) {
rvhi->media_player_manager()->DetachExternalVideoSurface(
static_cast<int>(player_id));
}
#endif
}
jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
......
......@@ -21,6 +21,7 @@
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_f.h"
struct WebMenuItem;
......@@ -268,6 +269,7 @@ class ContentViewCoreImpl : public ContentViewCore,
const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap);
void RequestExternalVideoSurface(int player_id);
void NotifyGeometryChange(int player_id, const gfx::RectF& rect);
// --------------------------------------------------------------------------
// Methods called from native code
......
......@@ -45,8 +45,12 @@ bool MediaPlayerManagerAndroid::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
DestroyAllMediaPlayers)
#if defined(GOOGLE_TV)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_RequestExternalSurface,
OnRequestExternalSurface)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyGeometryChange,
OnNotifyGeometryChange)
#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
......@@ -199,6 +203,7 @@ void MediaPlayerManagerAndroid::DestroyAllMediaPlayers() {
}
}
#if defined(GOOGLE_TV)
void MediaPlayerManagerAndroid::AttachExternalVideoSurface(int player_id,
jobject surface) {
MediaPlayerBridge* player = GetPlayer(player_id);
......@@ -213,13 +218,26 @@ void MediaPlayerManagerAndroid::DetachExternalVideoSurface(int player_id) {
}
void MediaPlayerManagerAndroid::OnRequestExternalSurface(int player_id) {
if (web_contents_) {
WebContentsViewAndroid* view =
static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
if (view)
view->RequestExternalVideoSurface(player_id);
}
if (!web_contents_)
return;
WebContentsViewAndroid* view =
static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
if (view)
view->RequestExternalVideoSurface(player_id);
}
void MediaPlayerManagerAndroid::OnNotifyGeometryChange(int player_id,
const gfx::RectF& rect) {
if (!web_contents_)
return;
WebContentsViewAndroid* view =
static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
if (view)
view->NotifyGeometryChange(player_id, rect);
}
#endif
MediaPlayerBridge* MediaPlayerManagerAndroid::GetPlayer(int player_id) {
for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
......
......@@ -16,6 +16,7 @@
#include "googleurl/src/gurl.h"
#include "media/base/android/media_player_bridge.h"
#include "media/base/android/media_player_bridge_manager.h"
#include "ui/gfx/rect_f.h"
namespace content {
......@@ -65,8 +66,10 @@ class MediaPlayerManagerAndroid
// Release all the players managed by this object.
void DestroyAllMediaPlayers();
#if defined(GOOGLE_TV)
void AttachExternalVideoSurface(int player_id, jobject surface);
void DetachExternalVideoSurface(int player_id);
#endif
media::MediaPlayerBridge* GetFullscreenPlayer();
media::MediaPlayerBridge* GetPlayer(int player_id);
......@@ -82,7 +85,10 @@ class MediaPlayerManagerAndroid
void OnPause(int player_id);
void OnReleaseResources(int player_id);
void OnDestroyPlayer(int player_id);
#if defined(GOOGLE_TV)
void OnRequestExternalSurface(int player_id);
void OnNotifyGeometryChange(int player_id, const gfx::RectF& rect);
#endif
// An array of managed players.
ScopedVector<media::MediaPlayerBridge> players_;
......
......@@ -54,11 +54,19 @@ void WebContentsViewAndroid::SetContentViewCore(
}
}
#if defined(GOOGLE_TV)
void WebContentsViewAndroid::RequestExternalVideoSurface(int player_id) {
if (content_view_core_)
content_view_core_->RequestExternalVideoSurface(player_id);
}
void WebContentsViewAndroid::NotifyGeometryChange(int player_id,
const gfx::RectF& rect) {
if (content_view_core_)
content_view_core_->NotifyGeometryChange(player_id, rect);
}
#endif
gfx::NativeView WebContentsViewAndroid::GetNativeView() const {
return content_view_core_;
}
......
......@@ -11,6 +11,7 @@
#include "content/port/browser/web_contents_view_port.h"
#include "content/public/browser/web_contents_view_delegate.h"
#include "content/public/common/context_menu_params.h"
#include "ui/gfx/rect_f.h"
namespace content {
class ContentViewCoreImpl;
......@@ -28,7 +29,10 @@ class WebContentsViewAndroid : public WebContentsViewPort,
// by the UI frontend.
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
#if defined(GOOGLE_TV)
void RequestExternalVideoSurface(int player_id);
void NotifyGeometryChange(int player_id, const gfx::RectF& rect);
#endif
// WebContentsView implementation --------------------------------------------
virtual gfx::NativeView GetNativeView() const OVERRIDE;
......
......@@ -11,6 +11,7 @@
#include "content/common/content_export.h"
#include "googleurl/src/gurl.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/rect_f.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
......@@ -116,6 +117,13 @@ IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_EnterFullscreen,
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_ExitFullscreen,
int /* player_id */)
#if defined(GOOGLE_TV)
// Request the player to use external surface for rendering.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_RequestExternalSurface,
int /* player_id */)
// Request the player to use external surface for rendering.
IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_NotifyGeometryChange,
int /* player_id */,
gfx::RectF /* rect */)
#endif
......@@ -166,4 +166,7 @@ public class ContentViewClient {
public void onExternalVideoSurfaceRequested(int playerId) {
}
public void onGeometryChanged(int playerId, float x, float y, float height, float width) {
}
}
......@@ -2650,6 +2650,21 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient {
getContentViewClient().onExternalVideoSurfaceRequested(playerId);
}
@CalledByNative
private void notifyGeometryChange(int playerId, float x, float y, float width, float height) {
RenderCoordinates.NormalizedPoint topLeft = mRenderCoordinates.createNormalizedPoint();
RenderCoordinates.NormalizedPoint bottomRight = mRenderCoordinates.createNormalizedPoint();
topLeft.setLocalDip(x * getScale(), y * getScale());
bottomRight.setLocalDip((x + width) * getScale(), (y + height) * getScale());
getContentViewClient().onGeometryChanged(
playerId,
topLeft.getXPix(),
topLeft.getYPix(),
bottomRight.getXPix() - topLeft.getXPix(),
bottomRight.getYPix() - topLeft.getYPix());
}
private native int nativeInit(boolean hardwareAccelerated, boolean inputEventsDeliveredAtVSync,
int webContentsPtr, int windowAndroidPtr);
......
......@@ -181,10 +181,24 @@ void WebMediaPlayerProxyImplAndroid::ExitFullscreen(int player_id) {
Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id));
}
#if defined(GOOGLE_TV)
void WebMediaPlayerProxyImplAndroid::RequestExternalSurface(int player_id) {
Send(new MediaPlayerHostMsg_RequestExternalSurface(routing_id(), player_id));
}
void WebMediaPlayerProxyImplAndroid::DidCommitCompositorFrame() {
std::map<int, gfx::RectF> geometry_change;
manager_->RetrieveGeometryChanges(&geometry_change);
for (std::map<int, gfx::RectF>::iterator it = geometry_change.begin();
it != geometry_change.end();
++it) {
Send(new MediaPlayerHostMsg_NotifyGeometryChange(routing_id(),
it->first,
it->second));
}
}
#endif
webkit_media::WebMediaPlayerImplAndroid*
WebMediaPlayerProxyImplAndroid::GetWebMediaPlayer(int player_id) {
return static_cast<webkit_media::WebMediaPlayerImplAndroid*>(
......
......@@ -44,8 +44,13 @@ class WebMediaPlayerProxyImplAndroid
virtual void DestroyPlayer(int player_id) OVERRIDE;
virtual void EnterFullscreen(int player_id) OVERRIDE;
virtual void ExitFullscreen(int player_id) OVERRIDE;
#if defined(GOOGLE_TV)
virtual void RequestExternalSurface(int player_id) OVERRIDE;
// Methods inherited from RenderViewObserver.
virtual void DidCommitCompositorFrame() OVERRIDE;
#endif
private:
webkit_media::WebMediaPlayerImplAndroid* GetWebMediaPlayer(int player_id);
......
......@@ -95,10 +95,12 @@ void WebMediaPlayerAndroid::cancelLoad() {
}
void WebMediaPlayerAndroid::play() {
#if defined(GOOGLE_TV)
if (hasVideo() && needs_external_surface_) {
DCHECK(!needs_establish_peer_);
RequestExternalSurface();
}
#endif
if (hasVideo() && needs_establish_peer_)
EstablishSurfaceTexturePeer();
......@@ -414,6 +416,7 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
if (natural_size_.width == width && natural_size_.height == height)
return;
#if defined(GOOGLE_TV)
static bool has_switch = CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseExternalVideoSurfaceThresholdInPixels);
static int threshold = 0;
......@@ -430,6 +433,7 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
if (!paused())
RequestExternalSurface();
}
#endif
natural_size_.width = width;
natural_size_.height = height;
......@@ -554,4 +558,27 @@ void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
is_playing_ = is_playing;
}
#if defined(GOOGLE_TV)
bool WebMediaPlayerAndroid::RetrieveGeometryChange(gfx::RectF* rect) {
if (!video_weblayer_)
return false;
// Compute the geometry of video frame layer.
cc::Layer* layer = video_weblayer_->layer();
rect->set_size(layer->bounds());
while (layer) {
rect->Offset(layer->position().OffsetFromOrigin());
layer = layer->parent();
}
// Return false when the geometry hasn't been changed from the last time.
if (last_computed_rect_ == *rect)
return false;
// Store the changed geometry information when it is actually changed.
last_computed_rect_ = *rect;
return true;
}
#endif
} // namespace webkit_media
......@@ -17,6 +17,7 @@
#include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayer.h"
#include "ui/gfx/rect_f.h"
#include "webkit/media/android/stream_texture_factory_android.h"
namespace webkit {
......@@ -149,6 +150,13 @@ class WebMediaPlayerAndroid
// Detach the player from its manager.
void Detach();
#if defined(GOOGLE_TV)
// Retrieve geometry of the media player (i.e. location and size of the video
// frame) if changed. Returns true only if the geometry has been changed since
// the last call.
bool RetrieveGeometryChange(gfx::RectF* rect);
#endif
protected:
// Construct a WebMediaPlayerAndroid object with reference to the
// client, manager and stream texture factory.
......@@ -199,8 +207,10 @@ class WebMediaPlayerAndroid
WebMediaPlayerManagerAndroid* manager() const { return manager_; }
#if defined(GOOGLE_TV)
// Request external surface for out-of-band composition.
virtual void RequestExternalSurface() = 0;
#endif
private:
void ReallocateVideoFrame();
......@@ -275,6 +285,12 @@ class WebMediaPlayerAndroid
scoped_ptr<webkit::WebLayerImpl> video_weblayer_;
#if defined(GOOGLE_TV)
// A rectangle represents the geometry of video frame, when computed last
// time.
gfx::RectF last_computed_rect_;
#endif
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerAndroid);
};
......
......@@ -129,10 +129,12 @@ void WebMediaPlayerImplAndroid::Destroy() {
proxy_ = NULL;
}
#if defined(GOOGLE_TV)
void WebMediaPlayerImplAndroid::RequestExternalSurface() {
if (proxy_)
proxy_->RequestExternalSurface(player_id());
}
#endif
void WebMediaPlayerImplAndroid::SetVideoSurface(jobject j_surface) {}
......
......@@ -68,7 +68,9 @@ class WebMediaPlayerImplAndroid : public WebMediaPlayerAndroid {
virtual double GetCurrentTimeInternal() const OVERRIDE;
virtual void ReleaseResourcesInternal() OVERRIDE;
virtual void Destroy() OVERRIDE;
#if defined(GOOGLE_TV)
virtual void RequestExternalSurface() OVERRIDE;
#endif
WebKit::WebFrame* const frame_;
......
......@@ -4,6 +4,7 @@
#include "webkit/media/android/webmediaplayer_manager_android.h"
#include "ui/gfx/rect_f.h"
#include "webkit/media/android/webmediaplayer_android.h"
namespace webkit_media {
......@@ -14,7 +15,7 @@ WebMediaPlayerManagerAndroid::WebMediaPlayerManagerAndroid()
}
WebMediaPlayerManagerAndroid::~WebMediaPlayerManagerAndroid() {
std::map<int32, WebMediaPlayerAndroid*>::iterator player_it;
std::map<int, WebMediaPlayerAndroid*>::iterator player_it;
for (player_it = media_players_.begin();
player_it != media_players_.end(); ++player_it) {
WebMediaPlayerAndroid* player = player_it->second;
......@@ -33,7 +34,7 @@ void WebMediaPlayerManagerAndroid::UnregisterMediaPlayer(int player_id) {
}
void WebMediaPlayerManagerAndroid::ReleaseMediaResources() {
std::map<int32, WebMediaPlayerAndroid*>::iterator player_it;
std::map<int, WebMediaPlayerAndroid*>::iterator player_it;
for (player_it = media_players_.begin();
player_it != media_players_.end(); ++player_it) {
WebMediaPlayerAndroid* player = player_it->second;
......@@ -46,7 +47,7 @@ void WebMediaPlayerManagerAndroid::ReleaseMediaResources() {
WebMediaPlayerAndroid* WebMediaPlayerManagerAndroid::GetMediaPlayer(
int player_id) {
std::map<int32, WebMediaPlayerAndroid*>::iterator iter =
std::map<int, WebMediaPlayerAndroid*>::iterator iter =
media_players_.find(player_id);
if (iter != media_players_.end())
return iter->second;
......@@ -69,4 +70,24 @@ bool WebMediaPlayerManagerAndroid::IsInFullscreen(WebKit::WebFrame* frame) {
return fullscreen_frame_ == frame;
}
#if defined(GOOGLE_TV)
void WebMediaPlayerManagerAndroid::RetrieveGeometryChanges(
std::map<int, gfx::RectF>* changes) {
DCHECK(changes->empty());
for (std::map<int, WebMediaPlayerAndroid*>::iterator player_it =
media_players_.begin();
player_it != media_players_.end();
++player_it) {
WebMediaPlayerAndroid* player = player_it->second;
if (player && player->hasVideo()) {
gfx::RectF rect;
if (player->RetrieveGeometryChange(&rect)) {
(*changes)[player_it->first] = rect;
}
}
}
}
#endif
} // namespace webkit_media
......@@ -13,6 +13,10 @@ namespace WebKit {
class WebFrame;
}
namespace gfx {
class RectF;
}
namespace webkit_media {
class WebMediaPlayerAndroid;
......@@ -45,12 +49,17 @@ class WebMediaPlayerManagerAndroid {
// Get the pointer to WebMediaPlayerAndroid given the |player_id|.
WebMediaPlayerAndroid* GetMediaPlayer(int player_id);
#if defined(GOOGLE_TV)
// Get the list of media players with video geometry changes.
void RetrieveGeometryChanges(std::map<int, gfx::RectF>* changes);
#endif
private:
// Info for all available WebMediaPlayerAndroid on a page; kept so that
// we can enumerate them to send updates about tab focus and visibily.
std::map<int32, WebMediaPlayerAndroid*> media_players_;
std::map<int, WebMediaPlayerAndroid*> media_players_;
int32 next_media_player_id_;
int next_media_player_id_;
// WebFrame of the fullscreen video.
WebKit::WebFrame* fullscreen_frame_;
......
......@@ -45,8 +45,10 @@ class WebMediaPlayerProxyAndroid {
// Request the player to exit fullscreen.
virtual void ExitFullscreen(int player_id) = 0;
#if defined(GOOGLE_TV)
// Request an external surface for out-of-band compositing.
virtual void RequestExternalSurface(int player_id) = 0;
#endif
};
} // namespace webkit_media
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment