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

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: Addressed boliu's comments and 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
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..c38f86fdbe76ffb6ecddb114b62e1f52b03bc21a
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java
@@ -0,0 +1,211 @@
+// 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.graphics.RectF;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+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.
+ *
+ * Please contact ycheo@chromium.org or wonsik@chromium.org if you have any
+ * questions or issues for this class.
+ */
+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.
Ignacio Solla 2014/02/05 23:47:00 What does it mean that WebView does hole-punching
boliu 2014/02/06 00:12:06 Not owner of video hole code, so my answer might n
+ 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 ContentViewCore mContentViewCore;
+ private int mPlayerId = INVALID_PLAYER_ID;
+ private SurfaceView mSurfaceView;
+
+ private RectF mRect;
+
+ private float mX;
+ private float mY;
+ private int mWidth;
+ private int mHeight;
+
+ public ExternalVideoSurfaceContainer(ContentViewCore contentViewCore) {
+ assert contentViewCore != null;
+ mContentViewCore = contentViewCore;
+ initializeCurrentPositionOfSurfaceView();
+ }
+
+ /**
+ * Request to create the external video surface.
+ * @param playerId The ID of the media player.
+ */
+ public void requestExternalVideoSurface(int playerId) {
+ if (mPlayerId == playerId) return;
+
+ if (mPlayerId == INVALID_PLAYER_ID) {
+ setActiveContainer(this);
+ }
+
+ mPlayerId = playerId;
+ initializeCurrentPositionOfSurfaceView();
+
+ createSurfaceView();
+ }
+
+ /**
+ * Release the external video surface being used by the given player.
+ * @param playerId The ID of the media player.
+ */
+ public void releaseExternalVideoSurface(int playerId) {
+ if (mPlayerId != playerId) return;
+
+ releaseIfActiveContainer(this);
+
+ mPlayerId = INVALID_PLAYER_ID;
+ }
+
+ /**
+ * Release the external video surface being used by the current player.
+ */
+ public void releaseCurrentExternalVideoSurface() {
+ releaseExternalVideoSurface(mPlayerId);
+ }
+
+ private void initializeCurrentPositionOfSurfaceView() {
+ mX = Float.NaN;
+ mY = Float.NaN;
+ 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;
+ }
+
+ /**
+ * Notify the size or the location of the video element is changed.
+ * @param playerId The ID of the media player.
+ * @param rect The boundary rectangle of the video element.
+ */
+ public void notifyExternalVideoSurfacePositionChanged(int playerId, RectF rect) {
+ if (mPlayerId != playerId) return;
+ mRect = rect;
+ layOutSurfaceView();
+ }
+
+
+ /**
+ * Notify the RenderCoordinates is updated.
+ */
+ public void notifyExternalVideoSurfaceRenderCoordinatesChanged() {
+ 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(mRect.left, mRect.top);
+ bottomRight.setAbsoluteCss(mRect.right, mRect.bottom);
+ float top = topLeft.getYPix();
+ float left = topLeft.getXPix();
+ float bottom = bottomRight.getYPix();
+ float right = bottomRight.getXPix();
+
+ float x = left + renderCoordinates.getScrollXPix();
+ float y = 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) {
+ mContentViewCore.attachExternalVideoSurface(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) {
+ mContentViewCore.detachExternalVideoSurface(mPlayerId);
+ }
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698