| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.android_webview; | 5 package org.chromium.android_webview; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.graphics.Canvas; | 8 import android.graphics.Canvas; |
| 9 import android.view.Surface; | 9 import android.view.Surface; |
| 10 import android.view.SurfaceHolder; | 10 import android.view.SurfaceHolder; |
| 11 import android.view.SurfaceView; | 11 import android.view.SurfaceView; |
| 12 import android.view.ViewGroup; | 12 import android.view.ViewGroup; |
| 13 | 13 |
| 14 import com.google.common.annotations.VisibleForTesting; |
| 15 |
| 14 import org.chromium.base.CalledByNative; | 16 import org.chromium.base.CalledByNative; |
| 15 import org.chromium.base.JNINamespace; | 17 import org.chromium.base.JNINamespace; |
| 16 import org.chromium.content.browser.ContentViewCore; | 18 import org.chromium.content.browser.ContentViewCore; |
| 17 import org.chromium.content.browser.RenderCoordinates; | 19 import org.chromium.content.browser.RenderCoordinates; |
| 18 | 20 |
| 19 import java.lang.ref.WeakReference; | 21 import java.lang.ref.WeakReference; |
| 20 | 22 |
| 21 /** | 23 /** |
| 22 * This is a container for external video surfaces. | 24 * This is a container for external video surfaces. |
| 23 * The object is owned by the native peer and it is owned by WebContents. | 25 * The object is owned by the native peer and it is owned by WebContents. |
| 24 * | 26 * |
| 25 * The expected behavior of the media player on the video hole punching is as fo
llows. | 27 * The expected behavior of the media player on the video hole punching is as fo
llows. |
| 26 * 1) If it requests the surface, it will call requestExternalVideoSurface(). | 28 * 1) If it requests the surface, it will call requestExternalVideoSurface(). |
| 27 * When the resolution of the video is changed, it'll call requestExternalVid
eoSurface(). | 29 * When the resolution of the video is changed, it'll call requestExternalVid
eoSurface(). |
| 28 * 2) Whenever the size or the position of the video element is changed, it'll n
otify through | 30 * 2) Whenever the size or the position of the video element is changed, it'll n
otify through |
| 29 * onExternalVideoSurfacePositionChanged(). | 31 * onExternalVideoSurfacePositionChanged(). |
| 30 * 3) Whenever the page that contains the video element is scrolled or zoomed, | 32 * 3) Whenever the page that contains the video element is scrolled or zoomed, |
| 31 * onFrameInfoUpdated() will be called. | 33 * onFrameInfoUpdated() will be called. |
| 32 * 4) Usually steps 1) ~ 3) are repeated during the playback. | 34 * 4) Usually steps 1) ~ 3) are repeated during the playback. |
| 33 * 5) If the player no longer needs the surface any more, it'll call | 35 * 5) If the player no longer needs the surface any more, it'll call |
| 34 * releaseExternalVideoSurface(). | 36 * releaseExternalVideoSurface(). |
| 35 * | 37 * |
| 36 * Please contact ycheo@chromium.org or wonsik@chromium.org if you have any | 38 * Please contact ycheo@chromium.org or wonsik@chromium.org if you have any |
| 37 * questions or issues for this class. | 39 * questions or issues for this class. |
| 38 */ | 40 */ |
| 39 @JNINamespace("android_webview") | 41 @JNINamespace("android_webview") |
| 40 public class ExternalVideoSurfaceContainer implements SurfaceHolder.Callback { | 42 public class ExternalVideoSurfaceContainer implements SurfaceHolder.Callback { |
| 41 private static final int INVALID_PLAYER_ID = -1; | 43 protected static final int INVALID_PLAYER_ID = -1; |
| 42 | 44 |
| 43 // Because WebView does hole-punching by itself, instead, the hole-punching
logic | 45 // Because WebView does hole-punching by itself, instead, the hole-punching
logic |
| 44 // in SurfaceView can clear out some web elements like media control or subt
itle. | 46 // in SurfaceView can clear out some web elements like media control or subt
itle. |
| 45 // So we need to disable its hole-punching logic. | 47 // So we need to disable its hole-punching logic. |
| 46 private static class NoPunchingSurfaceView extends SurfaceView { | 48 private static class NoPunchingSurfaceView extends SurfaceView { |
| 47 public NoPunchingSurfaceView(Context context) { | 49 public NoPunchingSurfaceView(Context context) { |
| 48 super(context); | 50 super(context); |
| 49 } | 51 } |
| 50 // SurfaceView.dispatchDraw implementation punches a hole in the view hi
erarchy. | 52 // SurfaceView.dispatchDraw implementation punches a hole in the view hi
erarchy. |
| 51 // Disable this by making this a no-op. | 53 // Disable this by making this a no-op. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 71 private float mTop; | 73 private float mTop; |
| 72 private float mRight; | 74 private float mRight; |
| 73 private float mBottom; | 75 private float mBottom; |
| 74 | 76 |
| 75 // The physical location/size of the external video surface in pixels. | 77 // The physical location/size of the external video surface in pixels. |
| 76 private int mX; | 78 private int mX; |
| 77 private int mY; | 79 private int mY; |
| 78 private int mWidth; | 80 private int mWidth; |
| 79 private int mHeight; | 81 private int mHeight; |
| 80 | 82 |
| 83 /** |
| 84 * Factory class to facilitate dependency injection. |
| 85 */ |
| 86 public static class Factory { |
| 87 public ExternalVideoSurfaceContainer create( |
| 88 int nativeExternalVideoSurfaceContainer, ContentViewCore content
ViewCore) { |
| 89 return new ExternalVideoSurfaceContainer( |
| 90 nativeExternalVideoSurfaceContainer, contentViewCore); |
| 91 } |
| 92 } |
| 93 private static Factory sFactory = new Factory(); |
| 94 |
| 95 @VisibleForTesting |
| 96 public static void setFactory(Factory factory) { |
| 97 sFactory = factory; |
| 98 } |
| 99 |
| 81 @CalledByNative | 100 @CalledByNative |
| 82 private static ExternalVideoSurfaceContainer create( | 101 private static ExternalVideoSurfaceContainer create( |
| 83 int nativeExternalVideoSurfaceContainer, ContentViewCore contentView
Core) { | 102 int nativeExternalVideoSurfaceContainer, ContentViewCore contentView
Core) { |
| 84 return new ExternalVideoSurfaceContainer( | 103 return sFactory.create(nativeExternalVideoSurfaceContainer, contentViewC
ore); |
| 85 nativeExternalVideoSurfaceContainer, contentViewCore); | |
| 86 } | 104 } |
| 87 | 105 |
| 88 private ExternalVideoSurfaceContainer( | 106 protected ExternalVideoSurfaceContainer( |
| 89 int nativeExternalVideoSurfaceContainer, ContentViewCore contentView
Core) { | 107 int nativeExternalVideoSurfaceContainer, ContentViewCore contentView
Core) { |
| 90 assert contentViewCore != null; | 108 assert contentViewCore != null; |
| 91 mNativeExternalVideoSurfaceContainer = nativeExternalVideoSurfaceContain
er; | 109 mNativeExternalVideoSurfaceContainer = nativeExternalVideoSurfaceContain
er; |
| 92 mContentViewCore = contentViewCore; | 110 mContentViewCore = contentViewCore; |
| 93 initializeCurrentPositionOfSurfaceView(); | 111 initializeCurrentPositionOfSurfaceView(); |
| 94 } | 112 } |
| 95 | 113 |
| 96 /** | 114 /** |
| 97 * Called when a media player wants to request an external video surface. | 115 * Called when a media player wants to request an external video surface. |
| 98 * @param playerId The ID of the media player. | 116 * @param playerId The ID of the media player. |
| 99 */ | 117 */ |
| 100 @CalledByNative | 118 @CalledByNative |
| 101 private void requestExternalVideoSurface(int playerId) { | 119 protected void requestExternalVideoSurface(int playerId) { |
| 102 if (mPlayerId == playerId) return; | 120 if (mPlayerId == playerId) return; |
| 103 | 121 |
| 104 if (mPlayerId == INVALID_PLAYER_ID) { | 122 if (mPlayerId == INVALID_PLAYER_ID) { |
| 105 setActiveContainer(this); | 123 setActiveContainer(this); |
| 106 } | 124 } |
| 107 | 125 |
| 108 mPlayerId = playerId; | 126 mPlayerId = playerId; |
| 109 initializeCurrentPositionOfSurfaceView(); | 127 initializeCurrentPositionOfSurfaceView(); |
| 110 | 128 |
| 111 createSurfaceView(); | 129 createSurfaceView(); |
| 112 } | 130 } |
| 113 | 131 |
| 114 /** | 132 /** |
| 115 * Called when a media player wants to release an external video surface. | 133 * Called when a media player wants to release an external video surface. |
| 116 * @param playerId The ID of the media player. | 134 * @param playerId The ID of the media player. |
| 117 */ | 135 */ |
| 118 @CalledByNative | 136 @CalledByNative |
| 119 private void releaseExternalVideoSurface(int playerId) { | 137 protected void releaseExternalVideoSurface(int playerId) { |
| 120 if (mPlayerId != playerId) return; | 138 if (mPlayerId != playerId) return; |
| 121 | 139 |
| 122 releaseIfActiveContainer(this); | 140 releaseIfActiveContainer(this); |
| 123 | 141 |
| 124 mPlayerId = INVALID_PLAYER_ID; | 142 mPlayerId = INVALID_PLAYER_ID; |
| 125 } | 143 } |
| 126 | 144 |
| 127 @CalledByNative | 145 @CalledByNative |
| 128 private void destroy() { | 146 protected void destroy() { |
| 129 releaseExternalVideoSurface(mPlayerId); | 147 releaseExternalVideoSurface(mPlayerId); |
| 130 } | 148 } |
| 131 | 149 |
| 132 private void initializeCurrentPositionOfSurfaceView() { | 150 private void initializeCurrentPositionOfSurfaceView() { |
| 133 mX = Integer.MIN_VALUE; | 151 mX = Integer.MIN_VALUE; |
| 134 mY = Integer.MIN_VALUE; | 152 mY = Integer.MIN_VALUE; |
| 135 mWidth = 0; | 153 mWidth = 0; |
| 136 mHeight = 0; | 154 mHeight = 0; |
| 137 } | 155 } |
| 138 | 156 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 169 /** | 187 /** |
| 170 * Called when the position of the video element which uses the external | 188 * Called when the position of the video element which uses the external |
| 171 * video surface is changed. | 189 * video surface is changed. |
| 172 * @param playerId The ID of the media player. | 190 * @param playerId The ID of the media player. |
| 173 * @param left The absolute CSS X coordinate of the left side of the video e
lement. | 191 * @param left The absolute CSS X coordinate of the left side of the video e
lement. |
| 174 * @param top The absolute CSS Y coordinate of the top side of the video ele
ment. | 192 * @param top The absolute CSS Y coordinate of the top side of the video ele
ment. |
| 175 * @param right The absolute CSS X coordinate of the right side of the video
element. | 193 * @param right The absolute CSS X coordinate of the right side of the video
element. |
| 176 * @param bottom The absolute CSS Y coordinate of the bottom side of the vid
eo element. | 194 * @param bottom The absolute CSS Y coordinate of the bottom side of the vid
eo element. |
| 177 */ | 195 */ |
| 178 @CalledByNative | 196 @CalledByNative |
| 179 private void onExternalVideoSurfacePositionChanged( | 197 protected void onExternalVideoSurfacePositionChanged( |
| 180 int playerId, float left, float top, float right, float bottom) { | 198 int playerId, float left, float top, float right, float bottom) { |
| 181 if (mPlayerId != playerId) return; | 199 if (mPlayerId != playerId) return; |
| 182 | 200 |
| 183 mLeft = left; | 201 mLeft = left; |
| 184 mTop = top; | 202 mTop = top; |
| 185 mRight = right; | 203 mRight = right; |
| 186 mBottom = bottom; | 204 mBottom = bottom; |
| 187 | 205 |
| 188 layOutSurfaceView(); | 206 layOutSurfaceView(); |
| 189 } | 207 } |
| 190 | 208 |
| 191 /** | 209 /** |
| 192 * Called when the page that contains the video element is scrolled or zoome
d. | 210 * Called when the page that contains the video element is scrolled or zoome
d. |
| 193 */ | 211 */ |
| 194 @CalledByNative | 212 @CalledByNative |
| 195 private void onFrameInfoUpdated() { | 213 protected void onFrameInfoUpdated() { |
| 196 if (mPlayerId == INVALID_PLAYER_ID) return; | 214 if (mPlayerId == INVALID_PLAYER_ID) return; |
| 197 | 215 |
| 198 layOutSurfaceView(); | 216 layOutSurfaceView(); |
| 199 } | 217 } |
| 200 | 218 |
| 201 private void layOutSurfaceView() { | 219 private void layOutSurfaceView() { |
| 202 RenderCoordinates renderCoordinates = mContentViewCore.getRenderCoordina
tes(); | 220 RenderCoordinates renderCoordinates = mContentViewCore.getRenderCoordina
tes(); |
| 203 RenderCoordinates.NormalizedPoint topLeft = renderCoordinates.createNorm
alizedPoint(); | 221 RenderCoordinates.NormalizedPoint topLeft = renderCoordinates.createNorm
alizedPoint(); |
| 204 RenderCoordinates.NormalizedPoint bottomRight = renderCoordinates.create
NormalizedPoint(); | 222 RenderCoordinates.NormalizedPoint bottomRight = renderCoordinates.create
NormalizedPoint(); |
| 205 topLeft.setAbsoluteCss(mLeft, mTop); | 223 topLeft.setAbsoluteCss(mLeft, mTop); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 } | 268 } |
| 251 } | 269 } |
| 252 | 270 |
| 253 private native void nativeSurfaceCreated( | 271 private native void nativeSurfaceCreated( |
| 254 long nativeExternalVideoSurfaceContainerImpl, int playerId, Surface
surface); | 272 long nativeExternalVideoSurfaceContainerImpl, int playerId, Surface
surface); |
| 255 | 273 |
| 256 private native void nativeSurfaceDestroyed( | 274 private native void nativeSurfaceDestroyed( |
| 257 long nativeExternalVideoSurfaceContainerImpl, int playerId); | 275 long nativeExternalVideoSurfaceContainerImpl, int playerId); |
| 258 } | 276 } |
| 259 | 277 |
| OLD | NEW |