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

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: Created 6 years, 11 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..94faf0f12cced1721a88bae0ac95c93fffcaf97d
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java
@@ -0,0 +1,160 @@
+// Copyright 2013 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.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content.browser.RenderCoordinates;
+
+/**
+ * This is a container for external video surfaces.
+ */
+public class ExternalVideoSurfaceContainer implements SurfaceHolder.Callback {
+ private static final int INVALID_PLAYER_ID = -1;
+
+ // There can be at most 1 external video container. Note that this does not mean that there can
+ // be at most 1 SurfaceView inside the container.
+ private static class LazyHolder {
+ private static final ExternalVideoSurfaceContainer sContainer =
+ new ExternalVideoSurfaceContainer();
+ }
+
+ // 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);
+ }
+ @Override
+ protected void dispatchDraw(Canvas canvas) {} // Do nothing
boliu 2014/01/24 21:56:32 What does this do exactly? From the public docs, o
ycheo (away) 2014/01/28 13:08:53 Done.
+ }
+
+ // There can be at most 1 external video surface for now.
+ // TODO(wonsik): extend it to multiple surfaces.
boliu 2014/01/24 21:56:32 Ok. Should mention this in the comment.
boliu 2014/01/25 01:27:39 Misread the code. I think right now the second vid
ycheo (away) 2014/01/28 13:08:53 Yes, the second video kicks the first one off.
+ private NoPunchingSurfaceView mSurfaceView;
+
+ private ContentViewCore mContentViewCore = null;
boliu 2014/01/24 21:56:32 This reference is very scary because it will never
ycheo (away) 2014/01/28 13:08:53 Done.
+ private int mPlayerId = INVALID_PLAYER_ID;
+
+ private ExternalVideoSurfaceContainer() {}
+
+ /**
+ * Returns the ExternalVideoSurfaceContainer instance.
+ */
+ public static ExternalVideoSurfaceContainer getInstance() {
+ return LazyHolder.sContainer;
+ }
+
+ /**
+ * Request to associate an external video surface with the specific media player or
+ * notify the geometry change on the video surface.
+ * @param contentViewCore The ContentViewCore object associated with the player.
+ * @param playerId The ID of the media player.
+ * @param isRequest True if this call is for requesting to associate the external video surface
+ * with the given media player.
+ * @param rect The boundary rectangle of the video surface.
+ */
+ public void notifyExternalVideoSurface(
+ ContentViewCore contentViewCore, int playerId, boolean isRequest, RectF rect) {
+ assert contentViewCore != null && playerId != INVALID_PLAYER_ID;
+ if (isRequest) {
+ requestExternalVideoSurface(contentViewCore, playerId);
+ // fall-through
+ } else if (rect.isEmpty()) {
+ releaseExternalVideoSurface(contentViewCore, playerId);
+ return;
+ }
+ notifyGeometryChange(playerId, rect);
+ }
+
+ private void removeSurfaceView() {
+ if (mSurfaceView != null) {
+ mSurfaceView.getHolder().removeCallback(this);
+ mContentViewCore.getContainerView().removeView(mSurfaceView);
+ mSurfaceView = null;
+ }
+ }
+
+ private void createSurfaceView() {
+ mSurfaceView = new NoPunchingSurfaceView(mContentViewCore.getContext());
+ mSurfaceView.getHolder().addCallback(this);
+ mContentViewCore.getContainerView().addView(mSurfaceView);
+ }
+
+ private void requestExternalVideoSurface(ContentViewCore contentViewCore, int playerId) {
+ // Detach the surface from the previous player if attached previously.
+ if ((mContentViewCore != contentViewCore || mPlayerId != playerId)
+ && mContentViewCore != null && mPlayerId != INVALID_PLAYER_ID) {
+ mContentViewCore.detachExternalVideoSurface(mPlayerId);
+ }
+ if (mContentViewCore != contentViewCore) {
+ removeSurfaceView();
+ mContentViewCore = contentViewCore;
+ createSurfaceView();
+ }
+ // Attach the surface to the player.
+ Surface surface = mSurfaceView.getHolder().getSurface();
+ if (surface != null && surface.isValid()) {
+ mContentViewCore.attachExternalVideoSurface(playerId, surface);
+ }
+ mPlayerId = playerId;
+ }
+
+ private void releaseExternalVideoSurface(ContentViewCore contentViewCore, int playerId) {
+ if (mContentViewCore != contentViewCore || mPlayerId != playerId) return;
+
+ mContentViewCore.detachExternalVideoSurface(mPlayerId);
+ removeSurfaceView();
+ mContentViewCore = null;
+ mPlayerId = INVALID_PLAYER_ID;
+ }
+
+ private void notifyGeometryChange(int playerId, RectF rect) {
+ if (mContentViewCore == null || mPlayerId != playerId) return;
+
+ RenderCoordinates renderCoordinates = mContentViewCore.getRenderCoordinates();
+ RenderCoordinates.NormalizedPoint topLeft = renderCoordinates.createNormalizedPoint();
+ RenderCoordinates.NormalizedPoint bottomRight = renderCoordinates.createNormalizedPoint();
+ topLeft.setAbsoluteCss(rect.left, rect.top);
+ bottomRight.setAbsoluteCss(rect.right, rect.bottom);
+
+ float left = topLeft.getXPix();
+ float top = topLeft.getYPix();
+ float right = bottomRight.getXPix();
+ float bottom = bottomRight.getYPix();
+ mSurfaceView.setX(left + renderCoordinates.getScrollXPix());
+ mSurfaceView.setY(top + renderCoordinates.getScrollYPix());
+ ViewGroup.LayoutParams layoutParams = mSurfaceView.getLayoutParams();
+ layoutParams.width = (int) (right - left + 0.5);
+ layoutParams.height = (int) (bottom - top + 0.5);
+ mSurfaceView.requestLayout();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ if (mContentViewCore != null && mPlayerId != INVALID_PLAYER_ID) {
+ mContentViewCore.attachExternalVideoSurface(mPlayerId, holder.getSurface());
+ }
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ if (mContentViewCore != null && mPlayerId != INVALID_PLAYER_ID) {
+ mContentViewCore.detachExternalVideoSurface(mPlayerId);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698