Skip to content

Commit 6df5ca0

Browse files
Teng-Hui ZhuAndroid (Google) Code Review
authored andcommitted
Merge "Avoid inline->fullscreen reload for html5 video." into jb-dev
2 parents c9c275f + c2b06d5 commit 6df5ca0

File tree

4 files changed

+74
-55
lines changed

4 files changed

+74
-55
lines changed

core/java/android/webkit/HTML5VideoFullScreen.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ public void surfaceDestroyed(SurfaceHolder holder)
104104
// After we return from this we can't use the surface any more.
105105
// The current Video View will be destroy when we play a new video.
106106
pauseAndDispatch(mProxy);
107+
// TODO: handle full screen->inline mode transition without a reload.
107108
mPlayer.release();
109+
mPlayer = null;
108110
mSurfaceHolder = null;
109111
if (mMediaController != null) {
110112
mMediaController.hide();
@@ -128,12 +130,12 @@ private SurfaceView getSurfaceView() {
128130
return mVideoSurfaceView;
129131
}
130132

131-
HTML5VideoFullScreen(Context context, int videoLayerId, int position) {
133+
HTML5VideoFullScreen(Context context, int videoLayerId, int position, boolean skipPrepare) {
132134
mVideoSurfaceView = new VideoSurfaceView(context);
133135
mFullScreenMode = FULLSCREEN_OFF;
134136
mVideoWidth = 0;
135137
mVideoHeight = 0;
136-
init(videoLayerId, position);
138+
init(videoLayerId, position, skipPrepare);
137139
}
138140

139141
private void setMediaController(MediaController m) {
@@ -156,8 +158,6 @@ public void decideDisplayMode() {
156158
}
157159

158160
private void prepareForFullScreen() {
159-
// So in full screen, we reset the MediaPlayer
160-
mPlayer.reset();
161161
MediaController mc = new FullScreenMediaController(mProxy.getContext(), mLayout);
162162
mc.setSystemUiVisibility(mLayout.getSystemUiVisibility());
163163
setMediaController(mc);
@@ -243,7 +243,7 @@ public void onCustomViewHidden() {
243243

244244
// Don't show the controller after exiting the full screen.
245245
mMediaController = null;
246-
mCurrentState = STATE_RELEASED;
246+
mCurrentState = STATE_RESETTED;
247247
}
248248
};
249249

core/java/android/webkit/HTML5VideoInline.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class HTML5VideoInline extends HTML5VideoView{
2121
// associated with the surface texture can be used for showing the screen
2222
// shot when paused, so they are not singleton.
2323
private static SurfaceTexture mSurfaceTexture = null;
24-
private int[] mTextureNames;
24+
private static int[] mTextureNames = null;
2525
// Every time when the VideoLayer Id change, we need to recreate the
2626
// SurfaceTexture in order to delete the old video's decoder memory.
2727
private static int mVideoLayerUsingSurfaceTexture = -1;
@@ -35,8 +35,7 @@ public void start() {
3535
}
3636

3737
HTML5VideoInline(int videoLayerId, int position) {
38-
init(videoLayerId, position);
39-
mTextureNames = null;
38+
init(videoLayerId, position, false);
4039
}
4140

4241
@Override
@@ -69,15 +68,14 @@ public void pauseAndDispatch(HTML5VideoViewProxy proxy) {
6968

7069
// Inline Video specific FUNCTIONS:
7170

72-
@Override
73-
public SurfaceTexture getSurfaceTexture(int videoLayerId) {
71+
public static SurfaceTexture getSurfaceTexture(int videoLayerId) {
7472
// Create the surface texture.
7573
if (videoLayerId != mVideoLayerUsingSurfaceTexture
7674
|| mSurfaceTexture == null
7775
|| mTextureNames == null) {
78-
if (mTextureNames != null) {
79-
GLES20.glDeleteTextures(1, mTextureNames, 0);
80-
}
76+
// The GL texture will store in the VideoLayerManager at native side.
77+
// They will be clean up when requested.
78+
// The reason we recreated GL texture name is for screen shot support.
8179
mTextureNames = new int[1];
8280
GLES20.glGenTextures(1, mTextureNames, 0);
8381
mSurfaceTexture = new SurfaceTexture(mTextureNames[0]);

core/java/android/webkit/HTML5VideoView.java

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
3131
// NOTE: these values are in sync with VideoLayerAndroid.h in webkit side.
3232
// Please keep them in sync when changed.
3333
static final int STATE_INITIALIZED = 0;
34-
static final int STATE_NOTPREPARED = 1;
34+
static final int STATE_PREPARING = 1;
3535
static final int STATE_PREPARED = 2;
3636
static final int STATE_PLAYING = 3;
37-
static final int STATE_RELEASED = 4;
38-
protected int mCurrentState;
37+
static final int STATE_RESETTED = 4;
3938

4039
protected HTML5VideoViewProxy mProxy;
4140

@@ -46,11 +45,11 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
4645
// This is used to find the VideoLayer on the native side.
4746
protected int mVideoLayerId;
4847

49-
// Every video will have one MediaPlayer. Given the fact we only have one
50-
// SurfaceTexture, there is only one MediaPlayer in action. Every time we
51-
// switch videos, a new instance of MediaPlayer will be created in reset().
52-
// Switching between inline and full screen will also create a new instance.
53-
protected MediaPlayer mPlayer;
48+
// Given the fact we only have one SurfaceTexture, we cannot support multiple
49+
// player at the same time. We may recreate a new one and abandon the old
50+
// one at transition time.
51+
protected static MediaPlayer mPlayer = null;
52+
protected static int mCurrentState = -1;
5453

5554
// We need to save such info.
5655
protected Uri mUri;
@@ -60,10 +59,12 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
6059
// See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
6160
protected static Timer mTimer;
6261

62+
protected boolean mPauseDuringPreparing;
63+
6364
// The spec says the timer should fire every 250 ms or less.
6465
private static final int TIMEUPDATE_PERIOD = 250; // ms
66+
private boolean mSkipPrepare = false;
6567

66-
protected boolean mPauseDuringPreparing;
6768
// common Video control FUNCTIONS:
6869
public void start() {
6970
if (mCurrentState == STATE_PREPARED) {
@@ -83,7 +84,7 @@ public void start() {
8384
public void pause() {
8485
if (isPlaying()) {
8586
mPlayer.pause();
86-
} else if (mCurrentState == STATE_NOTPREPARED) {
87+
} else if (mCurrentState == STATE_PREPARING) {
8788
mPauseDuringPreparing = true;
8889
}
8990
// Delete the Timer to stop it since there is no stop call.
@@ -124,11 +125,11 @@ public boolean isPlaying() {
124125
}
125126
}
126127

127-
public void release() {
128-
if (mCurrentState != STATE_RELEASED) {
129-
mPlayer.release();
128+
public void reset() {
129+
if (mCurrentState != STATE_RESETTED) {
130+
mPlayer.reset();
130131
}
131-
mCurrentState = STATE_RELEASED;
132+
mCurrentState = STATE_RESETTED;
132133
}
133134

134135
public void stopPlayback() {
@@ -142,9 +143,16 @@ public boolean getPauseDuringPreparing() {
142143
}
143144

144145
// Every time we start a new Video, we create a VideoView and a MediaPlayer
145-
public void init(int videoLayerId, int position) {
146-
mPlayer = new MediaPlayer();
147-
mCurrentState = STATE_INITIALIZED;
146+
public void init(int videoLayerId, int position, boolean skipPrepare) {
147+
if (mPlayer == null) {
148+
mPlayer = new MediaPlayer();
149+
mCurrentState = STATE_INITIALIZED;
150+
}
151+
mSkipPrepare = skipPrepare;
152+
// If we want to skip the prepare, then we keep the state.
153+
if (!mSkipPrepare) {
154+
mCurrentState = STATE_INITIALIZED;
155+
}
148156
mProxy = null;
149157
mVideoLayerId = videoLayerId;
150158
mSaveSeekTime = position;
@@ -195,17 +203,28 @@ public void setOnInfoListener(HTML5VideoViewProxy proxy) {
195203
}
196204

197205
public void prepareDataCommon(HTML5VideoViewProxy proxy) {
198-
try {
199-
mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders);
200-
mPlayer.prepareAsync();
201-
} catch (IllegalArgumentException e) {
202-
e.printStackTrace();
203-
} catch (IllegalStateException e) {
204-
e.printStackTrace();
205-
} catch (IOException e) {
206-
e.printStackTrace();
206+
if (!mSkipPrepare) {
207+
try {
208+
mPlayer.reset();
209+
mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders);
210+
mPlayer.prepareAsync();
211+
} catch (IllegalArgumentException e) {
212+
e.printStackTrace();
213+
} catch (IllegalStateException e) {
214+
e.printStackTrace();
215+
} catch (IOException e) {
216+
e.printStackTrace();
217+
}
218+
mCurrentState = STATE_PREPARING;
219+
} else {
220+
// If we skip prepare and the onPrepared happened in inline mode, we
221+
// don't need to call prepare again, we just need to call onPrepared
222+
// to refresh the state here.
223+
if (mCurrentState >= STATE_PREPARED) {
224+
onPrepared(mPlayer);
225+
}
226+
mSkipPrepare = false;
207227
}
208-
mCurrentState = STATE_NOTPREPARED;
209228
}
210229

211230
public void reprepareData(HTML5VideoViewProxy proxy) {
@@ -294,10 +313,6 @@ public boolean getReadyToUseSurfTex() {
294313
return false;
295314
}
296315

297-
public SurfaceTexture getSurfaceTexture(int videoLayerId) {
298-
return null;
299-
}
300-
301316
public void deleteSurfaceTexture() {
302317
}
303318

@@ -332,14 +347,14 @@ public boolean fullScreenExited() {
332347
return false;
333348
}
334349

335-
private boolean m_startWhenPrepared = false;
350+
private boolean mStartWhenPrepared = false;
336351

337352
public void setStartWhenPrepared(boolean willPlay) {
338-
m_startWhenPrepared = willPlay;
353+
mStartWhenPrepared = willPlay;
339354
}
340355

341356
public boolean getStartWhenPrepared() {
342-
return m_startWhenPrepared;
357+
return mStartWhenPrepared;
343358
}
344359

345360
}

core/java/android/webkit/HTML5VideoViewProxy.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,14 @@ public static void setBaseLayer(int layer) {
112112
mBaseLayer = layer;
113113

114114
int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
115-
SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(currentVideoLayerId);
115+
SurfaceTexture surfTexture =
116+
HTML5VideoInline.getSurfaceTexture(currentVideoLayerId);
116117
int textureName = mHTML5VideoView.getTextureName();
117118

118119
if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) {
119120
int playerState = mHTML5VideoView.getCurrentState();
120121
if (mHTML5VideoView.getPlayerBuffering())
121-
playerState = HTML5VideoView.STATE_NOTPREPARED;
122+
playerState = HTML5VideoView.STATE_PREPARING;
122123
boolean foundInTree = nativeSendSurfaceTexture(surfTexture,
123124
layer, currentVideoLayerId, textureName,
124125
playerState);
@@ -145,6 +146,7 @@ public static void enterFullScreenVideo(int layerId, String url,
145146
HTML5VideoViewProxy proxy, WebViewClassic webView) {
146147
// Save the inline video info and inherit it in the full screen
147148
int savePosition = 0;
149+
boolean canSkipPrepare = false;
148150
if (mHTML5VideoView != null) {
149151
// We don't allow enter full screen mode while the previous
150152
// full screen video hasn't finished yet.
@@ -156,15 +158,20 @@ public static void enterFullScreenVideo(int layerId, String url,
156158
// save the current position.
157159
if (layerId == mHTML5VideoView.getVideoLayerId()) {
158160
savePosition = mHTML5VideoView.getCurrentPosition();
161+
int playerState = mHTML5VideoView.getCurrentState();
162+
canSkipPrepare = (playerState == HTML5VideoView.STATE_PREPARING
163+
|| playerState == HTML5VideoView.STATE_PREPARED
164+
|| playerState == HTML5VideoView.STATE_PLAYING)
165+
&& !mHTML5VideoView.isFullScreenMode();
166+
}
167+
if (!canSkipPrepare) {
168+
mHTML5VideoView.reset();
159169
}
160-
mHTML5VideoView.release();
161170
}
162171
mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(),
163-
layerId, savePosition);
172+
layerId, savePosition, canSkipPrepare);
164173
mCurrentProxy = proxy;
165-
166174
mHTML5VideoView.setVideoURI(url, mCurrentProxy);
167-
168175
mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView);
169176
}
170177

@@ -217,8 +224,7 @@ public static void play(String url, int time, HTML5VideoViewProxy proxy,
217224
if (!backFromFullScreenMode) {
218225
mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
219226
}
220-
// release the media player to avoid finalize error
221-
mHTML5VideoView.release();
227+
mHTML5VideoView.reset();
222228
}
223229
mCurrentProxy = proxy;
224230
mHTML5VideoView = new HTML5VideoInline(videoLayerId, time);

0 commit comments

Comments
 (0)