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

Side by Side Diff: chromecast/shell/android/apk/src/org/chromium/chromecast/shell/ExternalVideoSurfaceContainer.java

Issue 638803002: Reorganizes Chromecast code to better reflect functional dependencies. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 2 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.chromecast.shell;
6
7 import android.content.Context;
8 import android.graphics.Canvas;
9 import android.view.Surface;
10 import android.view.SurfaceHolder;
11 import android.view.SurfaceView;
12 import android.view.ViewGroup;
13
14 import org.chromium.base.CalledByNative;
15 import org.chromium.base.JNINamespace;
16 import org.chromium.base.VisibleForTesting;
17 import org.chromium.content.browser.ContentViewCore;
18 import org.chromium.content.browser.RenderCoordinates;
19
20 import java.lang.ref.WeakReference;
21
22 /**
23 * This is a container for external video surfaces.
24 * The object is owned by the native peer and it is owned by WebContents.
25 *
26 * The expected behavior of the media player on the video hole punching is as fo llows.
27 * 1) If it requests the surface, it will call requestExternalVideoSurface().
28 * When the resolution of the video is changed, it'll call requestExternalVid eoSurface().
29 * 2) Whenever the size or the position of the video element is changed, it'll n otify through
30 * onExternalVideoSurfacePositionChanged().
31 * 3) Whenever the page that contains the video element is scrolled or zoomed,
32 * onFrameInfoUpdated() will be called.
33 * 4) Usually steps 1) ~ 3) are repeated during the playback.
34 * 5) If the player no longer needs the surface any more, it'll call
35 * releaseExternalVideoSurface().
36 *
37 * Please contact ycheo@chromium.org or wonsik@chromium.org if you have any
38 * questions or issues for this class.
39 *
40 * Note(gunsch): This class was copied wholesale from android_webview/native
41 * for the use of chromecast/. Owners of content/ have expressed not wanting
42 * this code in content/ to discourage usage, since they don't plan to support
43 * hole-punching long term. In the meantime, this copy is a workaround to avoid
44 * a dependency on android_webview.
45 */
46 @JNINamespace("chromecast::shell")
47 public class ExternalVideoSurfaceContainer implements SurfaceHolder.Callback {
48 protected static final int INVALID_PLAYER_ID = -1;
49
50 // Because WebView does hole-punching by itself, instead, the hole-punching logic
51 // in SurfaceView can clear out some web elements like media control or subt itle.
52 // So we need to disable its hole-punching logic.
53 private static class NoPunchingSurfaceView extends SurfaceView {
54 public NoPunchingSurfaceView(Context context) {
55 super(context);
56 }
57 // SurfaceView.dispatchDraw implementation punches a hole in the view hi erarchy.
58 // Disable this by making this a no-op.
59 @Override
60 protected void dispatchDraw(Canvas canvas) {}
61 }
62
63 // There can be at most 1 external video surface for now.
64 // If there are the multiple requests for the surface, then the second video will
65 // kick the first one off.
66 // To support the mulitple video surfaces seems impractical, because z-order between
67 // the multiple SurfaceViews is non-deterministic.
68 private static WeakReference<ExternalVideoSurfaceContainer> sActiveContainer =
69 new WeakReference<ExternalVideoSurfaceContainer>(null);
70
71 private final long mNativeExternalVideoSurfaceContainer;
72 private final ContentViewCore mContentViewCore;
73 private int mPlayerId = INVALID_PLAYER_ID;
74 private SurfaceView mSurfaceView;
75
76 // The absolute CSS coordinates of the video element.
77 private float mLeft;
78 private float mTop;
79 private float mRight;
80 private float mBottom;
81
82 // The physical location/size of the external video surface in pixels.
83 private int mX;
84 private int mY;
85 private int mWidth;
86 private int mHeight;
87
88 /**
89 * Factory class to facilitate dependency injection.
90 */
91 public static class Factory {
92 public ExternalVideoSurfaceContainer create(
93 long nativeExternalVideoSurfaceContainer, ContentViewCore conten tViewCore) {
94 return new ExternalVideoSurfaceContainer(
95 nativeExternalVideoSurfaceContainer, contentViewCore);
96 }
97 }
98 private static Factory sFactory = new Factory();
99
100 @VisibleForTesting
101 public static void setFactory(Factory factory) {
102 sFactory = factory;
103 }
104
105 @CalledByNative
106 private static ExternalVideoSurfaceContainer create(
107 long nativeExternalVideoSurfaceContainer, ContentViewCore contentVie wCore) {
108 return sFactory.create(nativeExternalVideoSurfaceContainer, contentViewC ore);
109 }
110
111 protected ExternalVideoSurfaceContainer(
112 long nativeExternalVideoSurfaceContainer, ContentViewCore contentVie wCore) {
113 assert contentViewCore != null;
114 mNativeExternalVideoSurfaceContainer = nativeExternalVideoSurfaceContain er;
115 mContentViewCore = contentViewCore;
116 initializeCurrentPositionOfSurfaceView();
117 }
118
119 /**
120 * Called when a media player wants to request an external video surface.
121 * @param playerId The ID of the media player.
122 */
123 @CalledByNative
124 protected void requestExternalVideoSurface(int playerId) {
125 if (mPlayerId == playerId) return;
126
127 if (mPlayerId == INVALID_PLAYER_ID) {
128 setActiveContainer(this);
129 }
130
131 mPlayerId = playerId;
132 initializeCurrentPositionOfSurfaceView();
133
134 createSurfaceView();
135 }
136
137 /**
138 * Called when a media player wants to release an external video surface.
139 * @param playerId The ID of the media player.
140 */
141 @CalledByNative
142 protected void releaseExternalVideoSurface(int playerId) {
143 if (mPlayerId != playerId) return;
144
145 releaseIfActiveContainer(this);
146
147 mPlayerId = INVALID_PLAYER_ID;
148 }
149
150 @CalledByNative
151 protected void destroy() {
152 releaseExternalVideoSurface(mPlayerId);
153 }
154
155 private void initializeCurrentPositionOfSurfaceView() {
156 mX = Integer.MIN_VALUE;
157 mY = Integer.MIN_VALUE;
158 mWidth = 0;
159 mHeight = 0;
160 }
161
162 private static void setActiveContainer(ExternalVideoSurfaceContainer contain er) {
163 ExternalVideoSurfaceContainer activeContainer = sActiveContainer.get();
164 if (activeContainer != null) {
165 activeContainer.removeSurfaceView();
166 }
167 sActiveContainer = new WeakReference<ExternalVideoSurfaceContainer>(cont ainer);
168 }
169
170 private static void releaseIfActiveContainer(ExternalVideoSurfaceContainer c ontainer) {
171 ExternalVideoSurfaceContainer activeContainer = sActiveContainer.get();
172 if (activeContainer == container) {
173 setActiveContainer(null);
174 }
175 }
176
177 private void createSurfaceView() {
178 mSurfaceView = new NoPunchingSurfaceView(mContentViewCore.getContext());
179 mSurfaceView.getHolder().addCallback(this);
180 // SurfaceHoder.surfaceCreated() will be called after the SurfaceView is attached to
181 // the Window and becomes visible.
182 mContentViewCore.getContainerView().addView(mSurfaceView);
183 }
184
185 private void removeSurfaceView() {
186 // SurfaceHoder.surfaceDestroyed() will be called in ViewGroup.removeVie w()
187 // as soon as the SurfaceView is detached from the Window.
188 mContentViewCore.getContainerView().removeView(mSurfaceView);
189 mSurfaceView = null;
190 }
191
192 /**
193 * Called when the position of the video element which uses the external
194 * video surface is changed.
195 * @param playerId The ID of the media player.
196 * @param left The absolute CSS X coordinate of the left side of the video e lement.
197 * @param top The absolute CSS Y coordinate of the top side of the video ele ment.
198 * @param right The absolute CSS X coordinate of the right side of the video element.
199 * @param bottom The absolute CSS Y coordinate of the bottom side of the vid eo element.
200 */
201 @CalledByNative
202 protected void onExternalVideoSurfacePositionChanged(
203 int playerId, float left, float top, float right, float bottom) {
204 if (mPlayerId != playerId) return;
205
206 mLeft = left;
207 mTop = top;
208 mRight = right;
209 mBottom = bottom;
210
211 layOutSurfaceView();
212 }
213
214 /**
215 * Called when the page that contains the video element is scrolled or zoome d.
216 */
217 @CalledByNative
218 protected void onFrameInfoUpdated() {
219 if (mPlayerId == INVALID_PLAYER_ID) return;
220
221 layOutSurfaceView();
222 }
223
224 private void layOutSurfaceView() {
225 RenderCoordinates renderCoordinates = mContentViewCore.getRenderCoordina tes();
226 RenderCoordinates.NormalizedPoint topLeft = renderCoordinates.createNorm alizedPoint();
227 RenderCoordinates.NormalizedPoint bottomRight = renderCoordinates.create NormalizedPoint();
228 topLeft.setAbsoluteCss(mLeft, mTop);
229 bottomRight.setAbsoluteCss(mRight, mBottom);
230 float top = topLeft.getYPix();
231 float left = topLeft.getXPix();
232 float bottom = bottomRight.getYPix();
233 float right = bottomRight.getXPix();
234
235 int x = Math.round(left + renderCoordinates.getScrollXPix());
236 int y = Math.round(top + renderCoordinates.getScrollYPix());
237 int width = Math.round(right - left);
238 int height = Math.round(bottom - top);
239 if (mX == x && mY == y && mWidth == width && mHeight == height) return;
240 mX = x;
241 mY = y;
242 mWidth = width;
243 mHeight = height;
244
245 mSurfaceView.setX(x);
246 mSurfaceView.setY(y);
247 ViewGroup.LayoutParams layoutParams = mSurfaceView.getLayoutParams();
248 layoutParams.width = width;
249 layoutParams.height = height;
250 mSurfaceView.requestLayout();
251 }
252
253 // SurfaceHolder.Callback methods.
254 @Override
255 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
256
257 @Override
258 // surfaceCreated() callback can be called regardless of requestExternalVide oSurface,
259 // if the activity comes back from the background and becomes visible.
260 public void surfaceCreated(SurfaceHolder holder) {
261 if (mPlayerId != INVALID_PLAYER_ID) {
262 nativeSurfaceCreated(
263 mNativeExternalVideoSurfaceContainer, mPlayerId, holder.getS urface());
264 }
265 }
266
267 // surfaceDestroyed() callback can be called regardless of releaseExternalVi deoSurface,
268 // if the activity moves to the backgound and becomes invisible.
269 @Override
270 public void surfaceDestroyed(SurfaceHolder holder) {
271 if (mPlayerId != INVALID_PLAYER_ID) {
272 nativeSurfaceDestroyed(mNativeExternalVideoSurfaceContainer, mPlayer Id);
273 }
274 }
275
276 private native void nativeSurfaceCreated(
277 long nativeExternalVideoSurfaceContainerImpl, int playerId, Surface surface);
278
279 private native void nativeSurfaceDestroyed(
280 long nativeExternalVideoSurfaceContainerImpl, int playerId);
281 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698