summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorycheo@chromium.org <ycheo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-21 16:08:20 +0000
committerycheo@chromium.org <ycheo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-21 16:08:20 +0000
commit8b4efe95a07d17eb46c86c9a55b0878b6838f01f (patch)
tree7e0603ea1c5805f2e05bad7c00b3eac878362c5f
parent578d5dae5655184ce0abed013a103e6d9e9875d2 (diff)
downloadchromium_src-8b4efe95a07d17eb46c86c9a55b0878b6838f01f.zip
chromium_src-8b4efe95a07d17eb46c86c9a55b0878b6838f01f.tar.gz
chromium_src-8b4efe95a07d17eb46c86c9a55b0878b6838f01f.tar.bz2
Enable the embedded L1/EME support in WebView.
- Add ExternalVideoSurfaceContainer which handles the external surface for the hole punching in WebView. - Refactor the callbacks of ContentViewClient on the hole-punching to make them have the single purpose per each function. BUG=329447 Review URL: https://codereview.chromium.org/132233042 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@252571 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java259
-rw-r--r--android_webview/lib/DEPS1
-rw-r--r--android_webview/lib/main/aw_main_delegate.cc6
-rw-r--r--android_webview/native/android_webview_jni_registrar.cc4
-rw-r--r--android_webview/native/external_video_surface_container_impl.cc112
-rw-r--r--android_webview/native/external_video_surface_container_impl.h57
-rw-r--r--android_webview/native/webview_native.gyp9
-rw-r--r--build/common.gypi6
-rw-r--r--content/browser/android/content_view_core_impl.cc53
-rw-r--r--content/browser/android/content_view_core_impl.h10
-rw-r--r--content/browser/media/android/browser_media_player_manager.cc42
-rw-r--r--content/browser/web_contents/web_contents_view_android.cc8
-rw-r--r--content/browser/web_contents/web_contents_view_android.h6
-rw-r--r--content/content_browser.gypi1
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java7
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java29
-rw-r--r--content/public/browser/android/external_video_surface_container.h61
17 files changed, 553 insertions, 118 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java b/android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java
new file mode 100644
index 0000000..7bc1e11
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java
@@ -0,0 +1,259 @@
+// Copyright 2014 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.
+
+package org.chromium.android_webview;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content.browser.RenderCoordinates;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * This is a container for external video surfaces.
+ * The object is owned by the native peer and it is owned by WebContents.
+ *
+ * The expected behavior of the media player on the video hole punching is as follows.
+ * 1) If it requests the surface, it will call requestExternalVideoSurface().
+ * When the resolution of the video is changed, it'll call requestExternalVideoSurface().
+ * 2) Whenever the size or the position of the video element is changed, it'll notify through
+ * onExternalVideoSurfacePositionChanged().
+ * 3) Whenever the page that contains the video element is scrolled or zoomed,
+ * onFrameInfoUpdated() will be called.
+ * 4) Usually steps 1) ~ 3) are repeated during the playback.
+ * 5) If the player no longer needs the surface any more, it'll call
+ * releaseExternalVideoSurface().
+ *
+ * Please contact ycheo@chromium.org or wonsik@chromium.org if you have any
+ * questions or issues for this class.
+ */
+@JNINamespace("android_webview")
+public class ExternalVideoSurfaceContainer implements SurfaceHolder.Callback {
+ private static final int INVALID_PLAYER_ID = -1;
+
+ // Because WebView does hole-punching by itself, instead, the hole-punching logic
+ // in SurfaceView can clear out some web elements like media control or subtitle.
+ // So we need to disable its hole-punching logic.
+ private static class NoPunchingSurfaceView extends SurfaceView {
+ public NoPunchingSurfaceView(Context context) {
+ super(context);
+ }
+ // SurfaceView.dispatchDraw implementation punches a hole in the view hierarchy.
+ // Disable this by making this a no-op.
+ @Override
+ protected void dispatchDraw(Canvas canvas) {}
+ }
+
+ // There can be at most 1 external video surface for now.
+ // If there are the multiple requests for the surface, then the second video will
+ // kick the first one off.
+ // To support the mulitple video surfaces seems impractical, because z-order between
+ // the multiple SurfaceViews is non-deterministic.
+ private static WeakReference<ExternalVideoSurfaceContainer> sActiveContainer =
+ new WeakReference<ExternalVideoSurfaceContainer>(null);
+
+ private final int mNativeExternalVideoSurfaceContainer;
+ private final ContentViewCore mContentViewCore;
+ private int mPlayerId = INVALID_PLAYER_ID;
+ private SurfaceView mSurfaceView;
+
+ // The absolute CSS coordinates of the video element.
+ private float mLeft;
+ private float mTop;
+ private float mRight;
+ private float mBottom;
+
+ // The physical location/size of the external video surface in pixels.
+ private int mX;
+ private int mY;
+ private int mWidth;
+ private int mHeight;
+
+ @CalledByNative
+ private static ExternalVideoSurfaceContainer create(
+ int nativeExternalVideoSurfaceContainer, ContentViewCore contentViewCore) {
+ return new ExternalVideoSurfaceContainer(
+ nativeExternalVideoSurfaceContainer, contentViewCore);
+ }
+
+ private ExternalVideoSurfaceContainer(
+ int nativeExternalVideoSurfaceContainer, ContentViewCore contentViewCore) {
+ assert contentViewCore != null;
+ mNativeExternalVideoSurfaceContainer = nativeExternalVideoSurfaceContainer;
+ mContentViewCore = contentViewCore;
+ initializeCurrentPositionOfSurfaceView();
+ }
+
+ /**
+ * Called when a media player wants to request an external video surface.
+ * @param playerId The ID of the media player.
+ */
+ @CalledByNative
+ private void requestExternalVideoSurface(int playerId) {
+ if (mPlayerId == playerId) return;
+
+ if (mPlayerId == INVALID_PLAYER_ID) {
+ setActiveContainer(this);
+ }
+
+ mPlayerId = playerId;
+ initializeCurrentPositionOfSurfaceView();
+
+ createSurfaceView();
+ }
+
+ /**
+ * Called when a media player wants to release an external video surface.
+ * @param playerId The ID of the media player.
+ */
+ @CalledByNative
+ private void releaseExternalVideoSurface(int playerId) {
+ if (mPlayerId != playerId) return;
+
+ releaseIfActiveContainer(this);
+
+ mPlayerId = INVALID_PLAYER_ID;
+ }
+
+ @CalledByNative
+ private void destroy() {
+ releaseExternalVideoSurface(mPlayerId);
+ }
+
+ private void initializeCurrentPositionOfSurfaceView() {
+ mX = Integer.MIN_VALUE;
+ mY = Integer.MIN_VALUE;
+ mWidth = 0;
+ mHeight = 0;
+ }
+
+ private static void setActiveContainer(ExternalVideoSurfaceContainer container) {
+ ExternalVideoSurfaceContainer activeContainer = sActiveContainer.get();
+ if (activeContainer != null) {
+ activeContainer.removeSurfaceView();
+ }
+ sActiveContainer = new WeakReference<ExternalVideoSurfaceContainer>(container);
+ }
+
+ private static void releaseIfActiveContainer(ExternalVideoSurfaceContainer container) {
+ ExternalVideoSurfaceContainer activeContainer = sActiveContainer.get();
+ if (activeContainer == container) {
+ setActiveContainer(null);
+ }
+ }
+
+ private void createSurfaceView() {
+ mSurfaceView = new NoPunchingSurfaceView(mContentViewCore.getContext());
+ mSurfaceView.getHolder().addCallback(this);
+ // SurfaceHoder.surfaceCreated() will be called after the SurfaceView is attached to
+ // the Window and becomes visible.
+ mContentViewCore.getContainerView().addView(mSurfaceView);
+ }
+
+ private void removeSurfaceView() {
+ // SurfaceHoder.surfaceDestroyed() will be called in ViewGroup.removeView()
+ // as soon as the SurfaceView is detached from the Window.
+ mContentViewCore.getContainerView().removeView(mSurfaceView);
+ mSurfaceView = null;
+ }
+
+ /**
+ * Called when the position of the video element which uses the external
+ * video surface is changed.
+ * @param playerId The ID of the media player.
+ * @param left The absolute CSS X coordinate of the left side of the video element.
+ * @param top The absolute CSS Y coordinate of the top side of the video element.
+ * @param right The absolute CSS X coordinate of the right side of the video element.
+ * @param bottom The absolute CSS Y coordinate of the bottom side of the video element.
+ */
+ @CalledByNative
+ private void onExternalVideoSurfacePositionChanged(
+ int playerId, float left, float top, float right, float bottom) {
+ if (mPlayerId != playerId) return;
+
+ mLeft = left;
+ mTop = top;
+ mRight = right;
+ mBottom = bottom;
+
+ layOutSurfaceView();
+ }
+
+ /**
+ * Called when the page that contains the video element is scrolled or zoomed.
+ */
+ @CalledByNative
+ private void onFrameInfoUpdated() {
+ if (mPlayerId == INVALID_PLAYER_ID) return;
+
+ layOutSurfaceView();
+ }
+
+ private void layOutSurfaceView() {
+ RenderCoordinates renderCoordinates = mContentViewCore.getRenderCoordinates();
+ RenderCoordinates.NormalizedPoint topLeft = renderCoordinates.createNormalizedPoint();
+ RenderCoordinates.NormalizedPoint bottomRight = renderCoordinates.createNormalizedPoint();
+ topLeft.setAbsoluteCss(mLeft, mTop);
+ bottomRight.setAbsoluteCss(mRight, mBottom);
+ float top = topLeft.getYPix();
+ float left = topLeft.getXPix();
+ float bottom = bottomRight.getYPix();
+ float right = bottomRight.getXPix();
+
+ int x = Math.round(left + renderCoordinates.getScrollXPix());
+ int y = Math.round(top + renderCoordinates.getScrollYPix());
+ int width = Math.round(right - left);
+ int height = Math.round(bottom - top);
+ if (mX == x && mY == y && mWidth == width && mHeight == height) return;
+ mX = x;
+ mY = y;
+ mWidth = width;
+ mHeight = height;
+
+ mSurfaceView.setX(x);
+ mSurfaceView.setY(y);
+ ViewGroup.LayoutParams layoutParams = mSurfaceView.getLayoutParams();
+ layoutParams.width = width;
+ layoutParams.height = height;
+ mSurfaceView.requestLayout();
+ }
+
+ // SurfaceHolder.Callback methods.
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
+
+ @Override
+ // surfaceCreated() callback can be called regardless of requestExternalVideoSurface,
+ // if the activity comes back from the background and becomes visible.
+ public void surfaceCreated(SurfaceHolder holder) {
+ if (mPlayerId != INVALID_PLAYER_ID) {
+ nativeSurfaceCreated(
+ mNativeExternalVideoSurfaceContainer, mPlayerId, holder.getSurface());
+ }
+ }
+
+ // surfaceDestroyed() callback can be called regardless of releaseExternalVideoSurface,
+ // if the activity moves to the backgound and becomes invisible.
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ if (mPlayerId != INVALID_PLAYER_ID) {
+ nativeSurfaceDestroyed(mNativeExternalVideoSurfaceContainer, mPlayerId);
+ }
+ }
+
+ private native void nativeSurfaceCreated(
+ long nativeExternalVideoSurfaceContainerImpl, int playerId, Surface surface);
+
+ private native void nativeSurfaceDestroyed(
+ long nativeExternalVideoSurfaceContainerImpl, int playerId);
+}
+
diff --git a/android_webview/lib/DEPS b/android_webview/lib/DEPS
index 8460d68..4442017 100644
--- a/android_webview/lib/DEPS
+++ b/android_webview/lib/DEPS
@@ -2,4 +2,5 @@ include_rules = [
"+cc/base/switches.h",
"+components", # For jni registers.
"+content/public",
+ "+media/base/media_switches.h", # For media command line switches.
]
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index c3186ae..8f8d387 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -26,6 +26,7 @@
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "gpu/command_buffer/service/in_process_command_buffer.h"
+#include "media/base/media_switches.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
namespace android_webview {
@@ -80,6 +81,11 @@ bool AwMainDelegate::BasicStartupComplete(int* exit_code) {
// Disable WebRTC.
cl->AppendSwitch(switches::kDisableWebRTC);
+#if defined(VIDEO_HOLE)
+ // Support EME/L1 with hole-punching.
+ cl->AppendSwitch(switches::kMediaDrmEnableNonCompositing);
+#endif
+
return false;
}
diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc
index 2a425b3..24241d7 100644
--- a/android_webview/native/android_webview_jni_registrar.cc
+++ b/android_webview/native/android_webview_jni_registrar.cc
@@ -19,6 +19,7 @@
#include "android_webview/native/aw_settings.h"
#include "android_webview/native/aw_web_contents_delegate.h"
#include "android_webview/native/cookie_manager.h"
+#include "android_webview/native/external_video_surface_container_impl.h"
#include "android_webview/native/input_stream_impl.h"
#include "android_webview/native/intercepted_request_data_impl.h"
#include "android_webview/native/java_browser_view_renderer_helper.h"
@@ -45,6 +46,9 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = {
{ "AwResource", AwResource::RegisterAwResource },
{ "AwWebContentsDelegate", RegisterAwWebContentsDelegate },
{ "CookieManager", RegisterCookieManager },
+#if defined(VIDEO_HOLE)
+ { "ExternalVideoSurfaceContainer", RegisterExternalVideoSurfaceContainer },
+#endif
{ "InterceptedRequestDataImpl", RegisterInterceptedRequestData },
{ "InputStream", RegisterInputStream },
{ "JavaBrowserViewRendererHelper", RegisterJavaBrowserViewRendererHelper },
diff --git a/android_webview/native/external_video_surface_container_impl.cc b/android_webview/native/external_video_surface_container_impl.cc
new file mode 100644
index 0000000..351b3ca
--- /dev/null
+++ b/android_webview/native/external_video_surface_container_impl.cc
@@ -0,0 +1,112 @@
+// Copyright 2014 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 "android_webview/native/external_video_surface_container_impl.h"
+
+#include "base/android/jni_android.h"
+#include "content/public/browser/android/content_view_core.h"
+#include "jni/ExternalVideoSurfaceContainer_jni.h"
+#include "ui/gfx/rect_f.h"
+
+using android_webview::ExternalVideoSurfaceContainerImpl;
+using base::android::AttachCurrentThread;
+using content::ContentViewCore;
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(ExternalVideoSurfaceContainerImpl);
+
+namespace content {
+
+// static
+void ExternalVideoSurfaceContainer::CreateForWebContents(
+ WebContents* web_contents) {
+ WebContentsUserData<ExternalVideoSurfaceContainerImpl>::CreateForWebContents(
+ web_contents);
+}
+
+// static
+ExternalVideoSurfaceContainer* ExternalVideoSurfaceContainer::FromWebContents(
+ WebContents* web_contents) {
+ return WebContentsUserData<ExternalVideoSurfaceContainerImpl>::
+ FromWebContents(web_contents);
+}
+
+} // namespace content
+
+namespace android_webview {
+
+ExternalVideoSurfaceContainerImpl::ExternalVideoSurfaceContainerImpl(
+ content::WebContents* web_contents) {
+ ContentViewCore* cvc = ContentViewCore::FromWebContents(web_contents);
+ if (cvc) {
+ JNIEnv* env = AttachCurrentThread();
+ jobject_.Reset(
+ Java_ExternalVideoSurfaceContainer_create(
+ env, reinterpret_cast<intptr_t>(this), cvc->GetJavaObject().obj()));
+ }
+}
+
+ExternalVideoSurfaceContainerImpl::~ExternalVideoSurfaceContainerImpl() {
+ JNIEnv* env = AttachCurrentThread();
+ Java_ExternalVideoSurfaceContainer_destroy(env, jobject_.obj());
+ jobject_.Reset();
+}
+
+void ExternalVideoSurfaceContainerImpl::RequestExternalVideoSurface(
+ int player_id,
+ const SurfaceCreatedCB& surface_created_cb,
+ const SurfaceDestroyedCB& surface_destroyed_cb) {
+ surface_created_cb_ = surface_created_cb;
+ surface_destroyed_cb_ = surface_destroyed_cb;
+
+ JNIEnv* env = AttachCurrentThread();
+ Java_ExternalVideoSurfaceContainer_requestExternalVideoSurface(
+ env, jobject_.obj(), static_cast<jint>(player_id));
+}
+
+void ExternalVideoSurfaceContainerImpl::ReleaseExternalVideoSurface(
+ int player_id) {
+ JNIEnv* env = AttachCurrentThread();
+ Java_ExternalVideoSurfaceContainer_releaseExternalVideoSurface(
+ env, jobject_.obj(), static_cast<jint>(player_id));
+
+ surface_created_cb_.Reset();
+ surface_destroyed_cb_.Reset();
+}
+
+void ExternalVideoSurfaceContainerImpl::OnFrameInfoUpdated() {
+ JNIEnv* env = AttachCurrentThread();
+ Java_ExternalVideoSurfaceContainer_onFrameInfoUpdated(env, jobject_.obj());
+}
+
+void ExternalVideoSurfaceContainerImpl::OnExternalVideoSurfacePositionChanged(
+ int player_id, const gfx::RectF& rect) {
+ JNIEnv* env = AttachCurrentThread();
+ Java_ExternalVideoSurfaceContainer_onExternalVideoSurfacePositionChanged(
+ env,
+ jobject_.obj(),
+ static_cast<jint>(player_id),
+ static_cast<jfloat>(rect.x()),
+ static_cast<jfloat>(rect.y()),
+ static_cast<jfloat>(rect.x() + rect.width()),
+ static_cast<jfloat>(rect.y() + rect.height()));
+}
+
+// Methods called from Java.
+void ExternalVideoSurfaceContainerImpl::SurfaceCreated(
+ JNIEnv* env, jobject obj, jint player_id, jobject jsurface) {
+ if (!surface_created_cb_.is_null())
+ surface_created_cb_.Run(static_cast<int>(player_id), jsurface);
+}
+
+void ExternalVideoSurfaceContainerImpl::SurfaceDestroyed(
+ JNIEnv* env, jobject obj, jint player_id) {
+ if (!surface_destroyed_cb_.is_null())
+ surface_destroyed_cb_.Run(static_cast<int>(player_id));
+}
+
+bool RegisterExternalVideoSurfaceContainer(JNIEnv* env) {
+ return RegisterNativesImpl(env) >= 0;
+}
+
+} // namespace android_webview
diff --git a/android_webview/native/external_video_surface_container_impl.h b/android_webview/native/external_video_surface_container_impl.h
new file mode 100644
index 0000000..c5d9f07
--- /dev/null
+++ b/android_webview/native/external_video_surface_container_impl.h
@@ -0,0 +1,57 @@
+// Copyright 2014 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 ANDROID_WEBVIEW_NATIVE_EXTERNAL_VIDEO_SURFACE_CONTAINER_IMPL_H_
+#define ANDROID_WEBVIEW_NATIVE_EXTERNAL_VIDEO_SURFACE_CONTAINER_IMPL_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "content/public/browser/android/external_video_surface_container.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace android_webview {
+
+class ExternalVideoSurfaceContainerImpl
+ : public content::ExternalVideoSurfaceContainer,
+ public content::WebContentsUserData<ExternalVideoSurfaceContainerImpl> {
+ public:
+ typedef base::Callback<void(int, jobject)> SurfaceCreatedCB;
+ typedef base::Callback<void(int)> SurfaceDestroyedCB;
+
+ ExternalVideoSurfaceContainerImpl(content::WebContents* contents);
+
+ // ExternalVideoSurfaceContainer implementation.
+ virtual void RequestExternalVideoSurface(
+ int player_id,
+ const SurfaceCreatedCB& surface_created_cb,
+ const SurfaceDestroyedCB& surface_destroyed_cb) OVERRIDE;
+ virtual void ReleaseExternalVideoSurface(int player_id) OVERRIDE;
+ virtual void OnFrameInfoUpdated() OVERRIDE;
+ virtual void OnExternalVideoSurfacePositionChanged(
+ int player_id, const gfx::RectF& rect) OVERRIDE;
+
+ // Methods called from Java.
+ void SurfaceCreated(
+ JNIEnv* env, jobject obj, jint player_id, jobject jsurface);
+ void SurfaceDestroyed(JNIEnv* env, jobject obj, jint player_id);
+
+ private:
+ virtual ~ExternalVideoSurfaceContainerImpl();
+
+ base::android::ScopedJavaGlobalRef<jobject> jobject_;
+
+ SurfaceCreatedCB surface_created_cb_;
+ SurfaceDestroyedCB surface_destroyed_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalVideoSurfaceContainerImpl);
+};
+
+bool RegisterExternalVideoSurfaceContainer(JNIEnv* env);
+
+} // namespace android_webview
+
+#endif // ANDROID_WEBVIEW_NATIVE_EXTERNAL_VIDEO_SURFACE_CONTAINER_IMPL_H_
diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp
index 8acb8b9..bfacd3b 100644
--- a/android_webview/native/webview_native.gyp
+++ b/android_webview/native/webview_native.gyp
@@ -81,6 +81,14 @@
'state_serializer.cc',
'state_serializer.h',
],
+ 'conditions': [
+ ['video_hole==1', {
+ 'sources': [
+ 'external_video_surface_container_impl.cc',
+ 'external_video_surface_container_impl.h',
+ ],
+ }],
+ ],
},
{
'target_name': 'input_stream_android_jar_jni_headers',
@@ -119,6 +127,7 @@
'../java/src/org/chromium/android_webview/AwResource.java',
'../java/src/org/chromium/android_webview/AwSettings.java',
'../java/src/org/chromium/android_webview/AwWebContentsDelegate.java',
+ '../java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java',
'../java/src/org/chromium/android_webview/InterceptedRequestData.java',
'../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java',
],
diff --git a/build/common.gypi b/build/common.gypi
index 72e0e73..594b9a2 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -1278,6 +1278,9 @@
# Force disable libstdc++ debug mode.
'disable_glibcxx_debug%': 0,
+ # Set to 1 to compile with the hole punching for the protected video.
+ 'video_hole%': 0,
+
'conditions': [
# The version of GCC in use, set later in platforms that use GCC and have
# not explicitly chosen to build with clang. Currently, this means all
@@ -2514,6 +2517,9 @@
'<(DEPTH)/chrome_elf/chrome_elf.gyp:chrome_redirects',
],
}],
+ ['video_hole==1', {
+ 'defines': ['VIDEO_HOLE=1'],
+ }],
], # conditions for 'target_defaults'
'target_conditions': [
['enable_wexit_time_destructors==1', {
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 2f120b4..89a1e5a 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -35,6 +35,7 @@
#include "content/common/input/web_input_event_traits.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/android/external_video_surface_container.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/favicon_status.h"
@@ -495,6 +496,12 @@ void ContentViewCoreImpl::UpdateFrameInfo(
controls_offset.y(),
content_offset.y(),
overdraw_bottom_height);
+#if defined(VIDEO_HOLE)
+ ExternalVideoSurfaceContainer* surface_container =
+ ExternalVideoSurfaceContainer::FromWebContents(web_contents_);
+ if (surface_container)
+ surface_container->OnFrameInfoUpdated();
+#endif // defined(VIDEO_HOLE)
}
void ContentViewCoreImpl::SetTitle(const base::string16& title) {
@@ -744,25 +751,6 @@ ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
}
-void ContentViewCoreImpl::NotifyExternalSurface(
- int player_id, bool is_request, const gfx::RectF& rect) {
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return;
-
- Java_ContentViewCore_notifyExternalSurface(
- env,
- obj.obj(),
- static_cast<jint>(player_id),
- static_cast<jboolean>(is_request),
- static_cast<jfloat>(rect.x()),
- static_cast<jfloat>(rect.y()),
- static_cast<jfloat>(rect.width()),
- static_cast<jfloat>(rect.height()));
-}
-
ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
JNIEnv* env = AttachCurrentThread();
@@ -1501,33 +1489,6 @@ jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
return web_contents_->ShowingInterstitialPage();
}
-void ContentViewCoreImpl::AttachExternalVideoSurface(JNIEnv* env,
- jobject obj,
- jint player_id,
- jobject jsurface) {
-#if defined(VIDEO_HOLE)
- 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 // defined(VIDEO_HOLE)
-}
-
-void ContentViewCoreImpl::DetachExternalVideoSurface(JNIEnv* env,
- jobject obj,
- jint player_id) {
-#if defined(VIDEO_HOLE)
- 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 // defined(VIDEO_HOLE)
-}
-
jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
jobject obj) {
RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index 9299f1c..80740f2 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -216,11 +216,6 @@ class ContentViewCoreImpl : public ContentViewCore,
jint delegate);
jboolean IsShowingInterstitialPage(JNIEnv* env, jobject obj);
- void AttachExternalVideoSurface(JNIEnv* env,
- jobject obj,
- jint player_id,
- jobject jsurface);
- void DetachExternalVideoSurface(JNIEnv* env, jobject obj, jint player_id);
void SetAccessibilityEnabled(JNIEnv* env, jobject obj, bool enabled);
void SendActionAfterDoubleTapUma(JNIEnv* env,
jobject obj,
@@ -290,11 +285,6 @@ class ContentViewCoreImpl : public ContentViewCore,
// testing/benchmarking purposes
base::android::ScopedJavaLocalRef<jobject> CreateTouchEventSynthesizer();
- // Notifies the java object about the external surface, requesting for one if
- // necessary.
- void NotifyExternalSurface(
- int player_id, bool is_request, const gfx::RectF& rect);
-
base::android::ScopedJavaLocalRef<jobject> GetContentVideoViewClient();
// Returns the context that the ContentViewCore was created with, it would
diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc
index b3d62bc..5d457e4 100644
--- a/content/browser/media/android/browser_media_player_manager.cc
+++ b/content/browser/media/android/browser_media_player_manager.cc
@@ -12,6 +12,7 @@
#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/common/media/media_player_messages_android.h"
#include "content/public/browser/android/content_view_core.h"
+#include "content/public/browser/android/external_video_surface_container.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
@@ -326,7 +327,12 @@ void BrowserMediaPlayerManager::RequestMediaResources(int player_id) {
}
void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
- // Nothing needs to be done.
+#if defined(VIDEO_HOLE)
+ ExternalVideoSurfaceContainer* surface_container =
+ ExternalVideoSurfaceContainer::FromWebContents(web_contents_);
+ if (surface_container)
+ surface_container->ReleaseExternalVideoSurface(player_id);
+#endif // defined(VIDEO_HOLE)
}
media::MediaResourceGetter*
@@ -464,10 +470,23 @@ void BrowserMediaPlayerManager::OnNotifyExternalSurface(
if (!web_contents_)
return;
- WebContentsViewAndroid* view =
- static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
- if (view)
- view->NotifyExternalSurface(player_id, is_request, rect);
+ ExternalVideoSurfaceContainer::CreateForWebContents(web_contents_);
+ ExternalVideoSurfaceContainer* surface_container =
+ ExternalVideoSurfaceContainer::FromWebContents(web_contents_);
+ if (!surface_container)
+ return;
+
+ if (is_request) {
+ // It's safe to use base::Unretained(this), because the callbacks will not
+ // be called after running ReleaseExternalVideoSurface().
+ surface_container->RequestExternalVideoSurface(
+ player_id,
+ base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface,
+ base::Unretained(this)),
+ base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface,
+ base::Unretained(this)));
+ }
+ surface_container->OnExternalVideoSurfacePositionChanged(player_id, rect);
}
#endif // defined(VIDEO_HOLE)
@@ -492,6 +511,12 @@ void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
return;
}
+#if defined(VIDEO_HOLE)
+ ExternalVideoSurfaceContainer* surface_container =
+ ExternalVideoSurfaceContainer::FromWebContents(web_contents_);
+ if (surface_container)
+ surface_container->ReleaseExternalVideoSurface(player_id);
+#endif // defined(VIDEO_HOLE)
if (video_view_.get()) {
fullscreen_player_id_ = player_id;
video_view_->OpenVideo();
@@ -570,13 +595,6 @@ void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
player->Release();
if (player_id == fullscreen_player_id_)
fullscreen_player_is_released_ = true;
-
-#if defined(VIDEO_HOLE)
- WebContentsViewAndroid* view =
- static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
- if (view)
- view->NotifyExternalSurface(player_id, false, gfx::RectF());
-#endif // defined(VIDEO_HOLE)
}
void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index fc024b7..76408a6 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -54,14 +54,6 @@ void WebContentsViewAndroid::SetContentViewCore(
}
}
-#if defined(VIDEO_HOLE)
-void WebContentsViewAndroid::NotifyExternalSurface(
- int player_id, bool is_request, const gfx::RectF& rect) {
- if (content_view_core_)
- content_view_core_->NotifyExternalSurface(player_id, is_request, rect);
-}
-#endif // defined(VIDEO_HOLE)
-
gfx::NativeView WebContentsViewAndroid::GetNativeView() const {
return content_view_core_ ? content_view_core_->GetViewAndroid() : NULL;
}
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h
index 3d043ec..aa2ef54 100644
--- a/content/browser/web_contents/web_contents_view_android.h
+++ b/content/browser/web_contents/web_contents_view_android.h
@@ -29,12 +29,6 @@ class WebContentsViewAndroid : public WebContentsViewPort,
// by the UI frontend.
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
-#if defined(VIDEO_HOLE)
- void NotifyExternalSurface(int player_id,
- bool is_request,
- const gfx::RectF& rect);
-#endif // defined(VIDEO_HOLE)
-
// WebContentsView implementation --------------------------------------------
virtual gfx::NativeView GetNativeView() const OVERRIDE;
virtual gfx::NativeView GetContentNativeView() const OVERRIDE;
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index e97081d..f24002d 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -40,6 +40,7 @@
'public/browser/android/content_view_layer_renderer.h',
'public/browser/android/devtools_auth.h',
'public/browser/android/download_controller_android.h',
+ 'public/browser/android/external_video_surface_container.h',
'public/browser/android/synchronous_compositor_client.h',
'public/browser/android/synchronous_compositor.cc',
'public/browser/android/synchronous_compositor.h',
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
index f870651..5ae5dbb 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
@@ -7,7 +7,6 @@ package org.chromium.content.browser;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
-import android.graphics.RectF;
import android.util.Log;
import android.view.ActionMode;
import android.view.KeyEvent;
@@ -161,12 +160,6 @@ public class ContentViewClient {
}
}
- public void onExternalVideoSurfaceRequested(int playerId) {
- }
-
- public void onGeometryChanged(int playerId, RectF rect) {
- }
-
public ContentVideoViewClient getContentVideoViewClient() {
return null;
}
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 9dea1cf..71cb9cd 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -16,7 +16,6 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -2553,9 +2552,6 @@ public class ContentViewCore
if (mBrowserAccessibilityManager != null) {
mBrowserAccessibilityManager.notifyFrameInfoInitialized();
}
-
- // Update geometry for external video surface.
- getContentViewClient().onGeometryChanged(-1, null);
}
@CalledByNative
@@ -3225,18 +3221,6 @@ public class ContentViewCore
return new Rect(x, y, right, bottom);
}
- public void attachExternalVideoSurface(int playerId, Surface surface) {
- if (mNativeContentViewCore != 0) {
- nativeAttachExternalVideoSurface(mNativeContentViewCore, playerId, surface);
- }
- }
-
- public void detachExternalVideoSurface(int playerId) {
- if (mNativeContentViewCore != 0) {
- nativeDetachExternalVideoSurface(mNativeContentViewCore, playerId);
- }
- }
-
private boolean onAnimate(long frameTimeMicros) {
if (mNativeContentViewCore == 0) return false;
return nativeOnAnimate(mNativeContentViewCore, frameTimeMicros);
@@ -3249,13 +3233,6 @@ public class ContentViewCore
}
}
- @CalledByNative
- private void notifyExternalSurface(
- int playerId, boolean isRequest, float x, float y, float width, float height) {
- if (isRequest) getContentViewClient().onExternalVideoSurfaceRequested(playerId);
- getContentViewClient().onGeometryChanged(playerId, new RectF(x, y, x + width, y + height));
- }
-
public void extractSmartClipData(int x, int y, int width, int height) {
if (mNativeContentViewCore != 0) {
nativeExtractSmartClipData(mNativeContentViewCore, x, y, width, height);
@@ -3465,12 +3442,6 @@ public class ContentViewCore
private native void nativeShowImeIfNeeded(long nativeContentViewCoreImpl);
- private native void nativeAttachExternalVideoSurface(
- long nativeContentViewCoreImpl, int playerId, Surface surface);
-
- private native void nativeDetachExternalVideoSurface(
- long nativeContentViewCoreImpl, int playerId);
-
private native void nativeSetAccessibilityEnabled(
long nativeContentViewCoreImpl, boolean enabled);
diff --git a/content/public/browser/android/external_video_surface_container.h b/content/public/browser/android/external_video_surface_container.h
new file mode 100644
index 0000000..1b630e1
--- /dev/null
+++ b/content/public/browser/android/external_video_surface_container.h
@@ -0,0 +1,61 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_ANDROID_EXTERNAL_VIDEO_SURFACE_CONTAINER_H_
+#define CONTENT_PUBLIC_BROWSER_ANDROID_EXTERNAL_VIDEO_SURFACE_CONTAINER_H_
+
+#include <jni.h>
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+
+namespace gfx {
+class RectF;
+}
+
+namespace content {
+class WebContents;
+
+// An interface used for managing the video surface for the hole punching.
+class CONTENT_EXPORT ExternalVideoSurfaceContainer {
+ public:
+ typedef base::Callback<void(int, jobject)> SurfaceCreatedCB;
+ typedef base::Callback<void(int)> SurfaceDestroyedCB;
+
+ // Creates an ExternalVideoSurfaceContainer, and attaches it to the given
+ // WebContents. If an instance is already attached, does nothing.
+ static void CreateForWebContents(WebContents* contents);
+
+ // Returns the existing ExternalVideoSurfaceContainer attached to the given
+ // WebContents or NULL.
+ static ExternalVideoSurfaceContainer* FromWebContents(WebContents* contents);
+
+ // Called when a media player wants to request an external video surface.
+ // Whenever the surface is created and visible, |surface_created_cb| will be
+ // called. And whenever it is destroyed or invisible, |surface_destroyed_cb|
+ // will be called.
+ virtual void RequestExternalVideoSurface(
+ int player_id,
+ const SurfaceCreatedCB& surface_created_cb,
+ const SurfaceDestroyedCB& surface_destroyed_cb) = 0;
+
+ // Called when a media player wants to release an external video surface.
+ virtual void ReleaseExternalVideoSurface(int player_id) = 0;
+
+ // Called when the position and size of the video element which uses
+ // the external video surface is changed.
+ // |rect| contains the new position and size in css pixels.
+ virtual void OnExternalVideoSurfacePositionChanged(
+ int player_id, const gfx::RectF& rect) = 0;
+
+ // Called when the page that contains the video element is scrolled or zoomed.
+ virtual void OnFrameInfoUpdated() = 0;
+
+ protected:
+ virtual ~ExternalVideoSurfaceContainer() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_ANDROID_EXTERNAL_VIDEO_SURFACE_CONTAINER_H_