Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java

Issue 132233042: Enable the embedded L1/EME support in WebView. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | android_webview/lib/DEPS » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java
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 0000000000000000000000000000000000000000..7bc1e11ca878ef4e01e9997fd544f206f89aa43c
--- /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);
+}
+
« no previous file with comments | « no previous file | android_webview/lib/DEPS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698