OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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.content.browser; | 5 package org.chromium.content.browser; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.app.AlertDialog; | 8 import android.app.AlertDialog; |
9 import android.content.Context; | 9 import android.content.Context; |
10 import android.content.DialogInterface; | 10 import android.content.DialogInterface; |
11 import android.graphics.Color; | |
12 import android.util.Log; | 11 import android.util.Log; |
13 import android.view.Gravity; | 12 import android.view.Gravity; |
14 import android.view.KeyEvent; | 13 import android.view.KeyEvent; |
15 import android.view.MotionEvent; | |
16 import android.view.Surface; | 14 import android.view.Surface; |
17 import android.view.SurfaceHolder; | 15 import android.view.SurfaceHolder; |
18 import android.view.SurfaceView; | 16 import android.view.SurfaceView; |
19 import android.view.View; | 17 import android.view.View; |
20 import android.view.ViewGroup; | 18 import android.view.ViewGroup; |
21 import android.widget.FrameLayout; | 19 import android.widget.FrameLayout; |
22 import android.widget.LinearLayout; | 20 import android.widget.LinearLayout; |
23 import android.widget.MediaController; | |
24 import android.widget.ProgressBar; | 21 import android.widget.ProgressBar; |
25 import android.widget.TextView; | 22 import android.widget.TextView; |
26 | 23 |
27 import org.chromium.base.CalledByNative; | 24 import org.chromium.base.CalledByNative; |
28 import org.chromium.base.JNINamespace; | 25 import org.chromium.base.JNINamespace; |
29 import org.chromium.base.ThreadUtils; | 26 import org.chromium.base.ThreadUtils; |
30 | 27 |
| 28 /** |
| 29 * This class implements accelerated fullscreen video playback using surface vie
w. |
| 30 */ |
31 @JNINamespace("content") | 31 @JNINamespace("content") |
32 public class ContentVideoView extends FrameLayout implements MediaController.Med
iaPlayerControl, | 32 public class ContentVideoView extends FrameLayout implements SurfaceHolder.Callb
ack { |
33 SurfaceHolder.Callback, View.OnTouchListener, View.OnKeyListener { | |
34 | 33 |
35 private static final String TAG = "ContentVideoView"; | 34 private static final String TAG = "ContentVideoView"; |
36 | 35 |
37 /* Do not change these values without updating their counterparts | 36 /* Do not change these values without updating their counterparts |
38 * in include/media/mediaplayer.h! | 37 * in include/media/mediaplayer.h! |
39 */ | 38 */ |
40 private static final int MEDIA_NOP = 0; // interface test message | 39 private static final int MEDIA_NOP = 0; // interface test message |
41 private static final int MEDIA_PREPARED = 1; | 40 private static final int MEDIA_PREPARED = 1; |
42 private static final int MEDIA_PLAYBACK_COMPLETE = 2; | 41 private static final int MEDIA_PLAYBACK_COMPLETE = 2; |
43 private static final int MEDIA_BUFFERING_UPDATE = 3; | 42 private static final int MEDIA_BUFFERING_UPDATE = 3; |
(...skipping 12 matching lines...) Expand all Loading... |
56 // all possible internal states | 55 // all possible internal states |
57 private static final int STATE_ERROR = -1; | 56 private static final int STATE_ERROR = -1; |
58 private static final int STATE_IDLE = 0; | 57 private static final int STATE_IDLE = 0; |
59 private static final int STATE_PLAYING = 1; | 58 private static final int STATE_PLAYING = 1; |
60 private static final int STATE_PAUSED = 2; | 59 private static final int STATE_PAUSED = 2; |
61 private static final int STATE_PLAYBACK_COMPLETED = 3; | 60 private static final int STATE_PLAYBACK_COMPLETED = 3; |
62 | 61 |
63 private SurfaceHolder mSurfaceHolder; | 62 private SurfaceHolder mSurfaceHolder; |
64 private int mVideoWidth; | 63 private int mVideoWidth; |
65 private int mVideoHeight; | 64 private int mVideoHeight; |
66 private int mCurrentBufferPercentage; | |
67 private int mDuration; | 65 private int mDuration; |
68 private MediaController mMediaController; | |
69 private boolean mCanPause; | |
70 private boolean mCanSeekBack; | |
71 private boolean mCanSeekForward; | |
72 | 66 |
73 // Native pointer to C++ ContentVideoView object. | 67 // Native pointer to C++ ContentVideoView object. |
74 private long mNativeContentVideoView; | 68 private long mNativeContentVideoView; |
75 | 69 |
76 // webkit should have prepared the media | 70 // webkit should have prepared the media |
77 private int mCurrentState = STATE_IDLE; | 71 private int mCurrentState = STATE_IDLE; |
78 | 72 |
79 // Strings for displaying media player errors | 73 // Strings for displaying media player errors |
80 private String mPlaybackErrorText; | 74 private String mPlaybackErrorText; |
81 private String mUnknownErrorText; | 75 private String mUnknownErrorText; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 LinearLayout.LayoutParams.WRAP_CONTENT, | 118 LinearLayout.LayoutParams.WRAP_CONTENT, |
125 LinearLayout.LayoutParams.WRAP_CONTENT)); | 119 LinearLayout.LayoutParams.WRAP_CONTENT)); |
126 mProgressBar = new ProgressBar(context, null, android.R.attr.progres
sBarStyleLarge); | 120 mProgressBar = new ProgressBar(context, null, android.R.attr.progres
sBarStyleLarge); |
127 mTextView = new TextView(context); | 121 mTextView = new TextView(context); |
128 mTextView.setText(videoLoadingText); | 122 mTextView.setText(videoLoadingText); |
129 addView(mProgressBar); | 123 addView(mProgressBar); |
130 addView(mTextView); | 124 addView(mTextView); |
131 } | 125 } |
132 } | 126 } |
133 | 127 |
134 private static class FullScreenMediaController extends MediaController { | |
135 | |
136 View mVideoView; | |
137 | |
138 public FullScreenMediaController(Context context, View video) { | |
139 super(context); | |
140 mVideoView = video; | |
141 } | |
142 | |
143 @Override | |
144 public void show() { | |
145 super.show(); | |
146 if (mVideoView != null) { | |
147 mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); | |
148 } | |
149 } | |
150 | |
151 @Override | |
152 public void hide() { | |
153 if (mVideoView != null) { | |
154 mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
); | |
155 } | |
156 super.hide(); | |
157 } | |
158 } | |
159 | |
160 private final Runnable mExitFullscreenRunnable = new Runnable() { | 128 private final Runnable mExitFullscreenRunnable = new Runnable() { |
161 @Override | 129 @Override |
162 public void run() { | 130 public void run() { |
163 exitFullscreen(true); | 131 exitFullscreen(true); |
164 } | 132 } |
165 }; | 133 }; |
166 | 134 |
167 private ContentVideoView(Context context, long nativeContentVideoView, | 135 protected ContentVideoView(Context context, long nativeContentVideoView, |
168 ContentVideoViewClient client) { | 136 ContentVideoViewClient client) { |
169 super(context); | 137 super(context); |
170 mNativeContentVideoView = nativeContentVideoView; | 138 mNativeContentVideoView = nativeContentVideoView; |
171 mClient = client; | 139 mClient = client; |
172 initResources(context); | 140 initResources(context); |
173 mCurrentBufferPercentage = 0; | |
174 mVideoSurfaceView = new VideoSurfaceView(context); | 141 mVideoSurfaceView = new VideoSurfaceView(context); |
175 setBackgroundColor(Color.BLACK); | |
176 showContentVideoView(); | 142 showContentVideoView(); |
177 setVisibility(View.VISIBLE); | 143 setVisibility(View.VISIBLE); |
178 mClient.onShowCustomView(this); | 144 mClient.onShowCustomView(this); |
179 } | 145 } |
180 | 146 |
181 private void initResources(Context context) { | 147 private void initResources(Context context) { |
182 if (mPlaybackErrorText != null) return; | 148 if (mPlaybackErrorText != null) return; |
183 mPlaybackErrorText = context.getString( | 149 mPlaybackErrorText = context.getString( |
184 org.chromium.content.R.string.media_player_error_text_invalid_pr
ogressive_playback); | 150 org.chromium.content.R.string.media_player_error_text_invalid_pr
ogressive_playback); |
185 mUnknownErrorText = context.getString( | 151 mUnknownErrorText = context.getString( |
186 org.chromium.content.R.string.media_player_error_text_unknown); | 152 org.chromium.content.R.string.media_player_error_text_unknown); |
187 mErrorButton = context.getString( | 153 mErrorButton = context.getString( |
188 org.chromium.content.R.string.media_player_error_button); | 154 org.chromium.content.R.string.media_player_error_button); |
189 mErrorTitle = context.getString( | 155 mErrorTitle = context.getString( |
190 org.chromium.content.R.string.media_player_error_title); | 156 org.chromium.content.R.string.media_player_error_title); |
191 mVideoLoadingText = context.getString( | 157 mVideoLoadingText = context.getString( |
192 org.chromium.content.R.string.media_player_loading_video); | 158 org.chromium.content.R.string.media_player_loading_video); |
193 } | 159 } |
194 | 160 |
195 private void showContentVideoView() { | 161 protected void showContentVideoView() { |
196 FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( | 162 mVideoSurfaceView.getHolder().addCallback(this); |
| 163 this.addView(mVideoSurfaceView, new FrameLayout.LayoutParams( |
197 ViewGroup.LayoutParams.MATCH_PARENT, | 164 ViewGroup.LayoutParams.MATCH_PARENT, |
198 ViewGroup.LayoutParams.MATCH_PARENT, | 165 ViewGroup.LayoutParams.MATCH_PARENT, |
199 Gravity.CENTER); | 166 Gravity.CENTER)); |
200 this.addView(mVideoSurfaceView, layoutParams); | 167 |
201 View progressView = mClient.getVideoLoadingProgressView(); | 168 mProgressView = mClient.getVideoLoadingProgressView(); |
202 if (progressView != null) { | 169 if (mProgressView == null) { |
203 mProgressView = progressView; | |
204 } else { | |
205 mProgressView = new ProgressView(getContext(), mVideoLoadingText); | 170 mProgressView = new ProgressView(getContext(), mVideoLoadingText); |
206 } | 171 } |
207 this.addView(mProgressView, new FrameLayout.LayoutParams( | 172 this.addView(mProgressView, new FrameLayout.LayoutParams( |
208 ViewGroup.LayoutParams.WRAP_CONTENT, | 173 ViewGroup.LayoutParams.WRAP_CONTENT, |
209 ViewGroup.LayoutParams.WRAP_CONTENT, | 174 ViewGroup.LayoutParams.WRAP_CONTENT, |
210 Gravity.CENTER)); | 175 Gravity.CENTER)); |
211 mVideoSurfaceView.setZOrderOnTop(true); | 176 } |
212 mVideoSurfaceView.setOnKeyListener(this); | 177 |
213 mVideoSurfaceView.setOnTouchListener(this); | 178 protected SurfaceView getSurfaceView() { |
214 mVideoSurfaceView.getHolder().addCallback(this); | 179 return mVideoSurfaceView; |
215 mVideoSurfaceView.setFocusable(true); | |
216 mVideoSurfaceView.setFocusableInTouchMode(true); | |
217 mVideoSurfaceView.requestFocus(); | |
218 } | 180 } |
219 | 181 |
220 @CalledByNative | 182 @CalledByNative |
221 public void onMediaPlayerError(int errorType) { | 183 public void onMediaPlayerError(int errorType) { |
222 Log.d(TAG, "OnMediaPlayerError: " + errorType); | 184 Log.d(TAG, "OnMediaPlayerError: " + errorType); |
223 if (mCurrentState == STATE_ERROR || mCurrentState == STATE_PLAYBACK_COMP
LETED) { | 185 if (mCurrentState == STATE_ERROR || mCurrentState == STATE_PLAYBACK_COMP
LETED) { |
224 return; | 186 return; |
225 } | 187 } |
226 | 188 |
227 // Ignore some invalid error codes. | 189 // Ignore some invalid error codes. |
228 if (errorType == MEDIA_ERROR_INVALID_CODE) { | 190 if (errorType == MEDIA_ERROR_INVALID_CODE) { |
229 return; | 191 return; |
230 } | 192 } |
231 | 193 |
232 mCurrentState = STATE_ERROR; | 194 mCurrentState = STATE_ERROR; |
233 if (mMediaController != null) { | |
234 mMediaController.hide(); | |
235 } | |
236 | 195 |
237 /* Pop up an error dialog so the user knows that | 196 /* Pop up an error dialog so the user knows that |
238 * something bad has happened. Only try and pop up the dialog | 197 * something bad has happened. Only try and pop up the dialog |
239 * if we're attached to a window. When we're going away and no | 198 * if we're attached to a window. When we're going away and no |
240 * longer have a window, don't bother showing the user an error. | 199 * longer have a window, don't bother showing the user an error. |
241 * | 200 * |
242 * TODO(qinmin): We need to review whether this Dialog is OK with | 201 * TODO(qinmin): We need to review whether this Dialog is OK with |
243 * the rest of the browser UI elements. | 202 * the rest of the browser UI elements. |
244 */ | 203 */ |
245 if (getWindowToken() != null) { | 204 if (getWindowToken() != null) { |
(...skipping 28 matching lines...) Expand all Loading... |
274 | 233 |
275 @CalledByNative | 234 @CalledByNative |
276 private void onVideoSizeChanged(int width, int height) { | 235 private void onVideoSizeChanged(int width, int height) { |
277 mVideoWidth = width; | 236 mVideoWidth = width; |
278 mVideoHeight = height; | 237 mVideoHeight = height; |
279 // This will trigger the SurfaceView.onMeasure() call. | 238 // This will trigger the SurfaceView.onMeasure() call. |
280 mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight); | 239 mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight); |
281 } | 240 } |
282 | 241 |
283 @CalledByNative | 242 @CalledByNative |
284 private void onBufferingUpdate(int percent) { | 243 protected void onBufferingUpdate(int percent) { |
285 mCurrentBufferPercentage = percent; | |
286 } | 244 } |
287 | 245 |
288 @CalledByNative | 246 @CalledByNative |
289 private void onPlaybackComplete() { | 247 private void onPlaybackComplete() { |
290 onCompletion(); | 248 onCompletion(); |
291 } | 249 } |
292 | 250 |
293 @CalledByNative | 251 @CalledByNative |
294 private void onUpdateMediaMetadata( | 252 protected void onUpdateMediaMetadata( |
295 int videoWidth, | 253 int videoWidth, |
296 int videoHeight, | 254 int videoHeight, |
297 int duration, | 255 int duration, |
298 boolean canPause, | 256 boolean canPause, |
299 boolean canSeekBack, | 257 boolean canSeekBack, |
300 boolean canSeekForward) { | 258 boolean canSeekForward) { |
| 259 mDuration = duration; |
301 mProgressView.setVisibility(View.GONE); | 260 mProgressView.setVisibility(View.GONE); |
302 mDuration = duration; | |
303 mCanPause = canPause; | |
304 mCanSeekBack = canSeekBack; | |
305 mCanSeekForward = canSeekForward; | |
306 mCurrentState = isPlaying() ? STATE_PLAYING : STATE_PAUSED; | 261 mCurrentState = isPlaying() ? STATE_PLAYING : STATE_PAUSED; |
307 if (mMediaController != null) { | |
308 mMediaController.setEnabled(true); | |
309 // If paused , should show the controller for ever. | |
310 if (isPlaying()) | |
311 mMediaController.show(); | |
312 else | |
313 mMediaController.show(0); | |
314 } | |
315 | |
316 onVideoSizeChanged(videoWidth, videoHeight); | 262 onVideoSizeChanged(videoWidth, videoHeight); |
317 } | 263 } |
318 | 264 |
319 @Override | 265 @Override |
320 public void surfaceChanged(SurfaceHolder holder, int format, int width, int
height) { | 266 public void surfaceChanged(SurfaceHolder holder, int format, int width, int
height) { |
321 mVideoSurfaceView.setFocusable(true); | |
322 mVideoSurfaceView.setFocusableInTouchMode(true); | |
323 if (isInPlaybackState() && mMediaController != null) { | |
324 mMediaController.show(); | |
325 } | |
326 } | 267 } |
327 | 268 |
328 @Override | 269 @Override |
329 public void surfaceCreated(SurfaceHolder holder) { | 270 public void surfaceCreated(SurfaceHolder holder) { |
330 mSurfaceHolder = holder; | 271 mSurfaceHolder = holder; |
331 openVideo(); | 272 openVideo(); |
332 } | 273 } |
333 | 274 |
334 @Override | 275 @Override |
335 public void surfaceDestroyed(SurfaceHolder holder) { | 276 public void surfaceDestroyed(SurfaceHolder holder) { |
336 if (mNativeContentVideoView != 0) { | 277 if (mNativeContentVideoView != 0) { |
337 nativeSetSurface(mNativeContentVideoView, null); | 278 nativeSetSurface(mNativeContentVideoView, null); |
338 } | 279 } |
339 mSurfaceHolder = null; | 280 mSurfaceHolder = null; |
340 post(mExitFullscreenRunnable); | 281 post(mExitFullscreenRunnable); |
341 } | 282 } |
342 | 283 |
343 private void setMediaController(MediaController controller) { | |
344 if (mMediaController != null) { | |
345 mMediaController.hide(); | |
346 } | |
347 mMediaController = controller; | |
348 attachMediaController(); | |
349 } | |
350 | |
351 private void attachMediaController() { | |
352 if (mMediaController != null) { | |
353 mMediaController.setMediaPlayer(this); | |
354 mMediaController.setAnchorView(mVideoSurfaceView); | |
355 mMediaController.setEnabled(false); | |
356 } | |
357 } | |
358 | |
359 @CalledByNative | 284 @CalledByNative |
360 private void openVideo() { | 285 protected void openVideo() { |
361 if (mSurfaceHolder != null) { | 286 if (mSurfaceHolder != null) { |
362 mCurrentState = STATE_IDLE; | 287 mCurrentState = STATE_IDLE; |
363 mCurrentBufferPercentage = 0; | |
364 setMediaController(new FullScreenMediaController(getContext(), this)
); | |
365 if (mNativeContentVideoView != 0) { | 288 if (mNativeContentVideoView != 0) { |
366 nativeUpdateMediaMetadata(mNativeContentVideoView); | 289 nativeUpdateMediaMetadata(mNativeContentVideoView); |
367 nativeSetSurface(mNativeContentVideoView, | 290 nativeSetSurface(mNativeContentVideoView, |
368 mSurfaceHolder.getSurface()); | 291 mSurfaceHolder.getSurface()); |
369 } | 292 } |
370 } | 293 } |
371 } | 294 } |
372 | 295 |
373 private void onCompletion() { | 296 protected void onCompletion() { |
374 mCurrentState = STATE_PLAYBACK_COMPLETED; | 297 mCurrentState = STATE_PLAYBACK_COMPLETED; |
375 if (mMediaController != null) { | |
376 mMediaController.hide(); | |
377 } | |
378 } | 298 } |
379 | 299 |
380 @Override | |
381 public boolean onTouch(View v, MotionEvent event) { | |
382 if (isInPlaybackState() && mMediaController != null && | |
383 event.getAction() == MotionEvent.ACTION_DOWN) { | |
384 toggleMediaControlsVisiblity(); | |
385 } | |
386 return true; | |
387 } | |
388 | 300 |
389 @Override | 301 protected boolean isInPlaybackState() { |
390 public boolean onTrackballEvent(MotionEvent ev) { | |
391 if (isInPlaybackState() && mMediaController != null) { | |
392 toggleMediaControlsVisiblity(); | |
393 } | |
394 return false; | |
395 } | |
396 | |
397 @Override | |
398 public boolean onKey(View v, int keyCode, KeyEvent event) { | |
399 boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && | |
400 keyCode != KeyEvent.KEYCODE_VOLUME_UP && | |
401 keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && | |
402 keyCode != KeyEvent.KEYCODE_VOLUME_MUTE && | |
403 keyCode != KeyEvent.KEYCODE_CALL && | |
404 keyCode != KeyEvent.KEYCODE_MENU && | |
405 keyCode != KeyEvent.KEYCODE_SEARCH && | |
406 keyCode != KeyEvent.KEYCODE_ENDCALL; | |
407 if (isInPlaybackState() && isKeyCodeSupported && mMediaController != nul
l) { | |
408 if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || | |
409 keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) { | |
410 if (isPlaying()) { | |
411 pause(); | |
412 mMediaController.show(); | |
413 } else { | |
414 start(); | |
415 mMediaController.hide(); | |
416 } | |
417 return true; | |
418 } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { | |
419 if (!isPlaying()) { | |
420 start(); | |
421 mMediaController.hide(); | |
422 } | |
423 return true; | |
424 } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP | |
425 || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { | |
426 if (isPlaying()) { | |
427 pause(); | |
428 mMediaController.show(); | |
429 } | |
430 return true; | |
431 } else { | |
432 toggleMediaControlsVisiblity(); | |
433 } | |
434 } else if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyE
vent.ACTION_UP) { | |
435 exitFullscreen(false); | |
436 return true; | |
437 } else if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCO
DE_SEARCH) { | |
438 return true; | |
439 } | |
440 return super.onKeyDown(keyCode, event); | |
441 } | |
442 | |
443 private void toggleMediaControlsVisiblity() { | |
444 if (mMediaController.isShowing()) { | |
445 mMediaController.hide(); | |
446 } else { | |
447 mMediaController.show(); | |
448 } | |
449 } | |
450 | |
451 private boolean isInPlaybackState() { | |
452 return (mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE); | 302 return (mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE); |
453 } | 303 } |
454 | 304 |
455 @Override | 305 protected void start() { |
456 public void start() { | |
457 if (isInPlaybackState()) { | 306 if (isInPlaybackState()) { |
458 if (mNativeContentVideoView != 0) { | 307 if (mNativeContentVideoView != 0) { |
459 nativePlay(mNativeContentVideoView); | 308 nativePlay(mNativeContentVideoView); |
460 } | 309 } |
461 mCurrentState = STATE_PLAYING; | 310 mCurrentState = STATE_PLAYING; |
462 } | 311 } |
463 } | 312 } |
464 | 313 |
465 @Override | 314 protected void pause() { |
466 public void pause() { | |
467 if (isInPlaybackState()) { | 315 if (isInPlaybackState()) { |
468 if (isPlaying()) { | 316 if (isPlaying()) { |
469 if (mNativeContentVideoView != 0) { | 317 if (mNativeContentVideoView != 0) { |
470 nativePause(mNativeContentVideoView); | 318 nativePause(mNativeContentVideoView); |
471 } | 319 } |
472 mCurrentState = STATE_PAUSED; | 320 mCurrentState = STATE_PAUSED; |
473 } | 321 } |
474 } | 322 } |
475 } | 323 } |
476 | 324 |
477 // cache duration as mDuration for faster access | 325 // cache duration as mDuration for faster access |
478 @Override | 326 protected int getDuration() { |
479 public int getDuration() { | |
480 if (isInPlaybackState()) { | 327 if (isInPlaybackState()) { |
481 if (mDuration > 0) { | 328 if (mDuration > 0) { |
482 return mDuration; | 329 return mDuration; |
483 } | 330 } |
484 if (mNativeContentVideoView != 0) { | 331 if (mNativeContentVideoView != 0) { |
485 mDuration = nativeGetDurationInMilliSeconds(mNativeContentVideoV
iew); | 332 mDuration = nativeGetDurationInMilliSeconds(mNativeContentVideoV
iew); |
486 } else { | 333 } else { |
487 mDuration = 0; | 334 mDuration = 0; |
488 } | 335 } |
489 return mDuration; | 336 return mDuration; |
490 } | 337 } |
491 mDuration = -1; | 338 mDuration = -1; |
492 return mDuration; | 339 return mDuration; |
493 } | 340 } |
494 | 341 |
495 @Override | 342 protected int getCurrentPosition() { |
496 public int getCurrentPosition() { | |
497 if (isInPlaybackState() && mNativeContentVideoView != 0) { | 343 if (isInPlaybackState() && mNativeContentVideoView != 0) { |
498 return nativeGetCurrentPosition(mNativeContentVideoView); | 344 return nativeGetCurrentPosition(mNativeContentVideoView); |
499 } | 345 } |
500 return 0; | 346 return 0; |
501 } | 347 } |
502 | 348 |
503 @Override | 349 protected void seekTo(int msec) { |
504 public void seekTo(int msec) { | |
505 if (mNativeContentVideoView != 0) { | 350 if (mNativeContentVideoView != 0) { |
506 nativeSeekTo(mNativeContentVideoView, msec); | 351 nativeSeekTo(mNativeContentVideoView, msec); |
507 } | 352 } |
508 } | 353 } |
509 | 354 |
510 @Override | 355 protected boolean isPlaying() { |
511 public boolean isPlaying() { | |
512 return mNativeContentVideoView != 0 && nativeIsPlaying(mNativeContentVid
eoView); | 356 return mNativeContentVideoView != 0 && nativeIsPlaying(mNativeContentVid
eoView); |
513 } | 357 } |
514 | 358 |
515 @Override | |
516 public int getBufferPercentage() { | |
517 return mCurrentBufferPercentage; | |
518 } | |
519 | |
520 @Override | |
521 public boolean canPause() { | |
522 return mCanPause; | |
523 } | |
524 | |
525 @Override | |
526 public boolean canSeekBackward() { | |
527 return mCanSeekBack; | |
528 } | |
529 | |
530 @Override | |
531 public boolean canSeekForward() { | |
532 return mCanSeekForward; | |
533 } | |
534 | |
535 @Override | |
536 public int getAudioSessionId() { | |
537 return 0; | |
538 } | |
539 | |
540 @CalledByNative | 359 @CalledByNative |
541 private static ContentVideoView createContentVideoView( | 360 private static ContentVideoView createContentVideoView( |
542 Context context, long nativeContentVideoView, ContentVideoViewClient
client) { | 361 Context context, long nativeContentVideoView, ContentVideoViewClient
client, |
| 362 boolean legacy) { |
543 ThreadUtils.assertOnUiThread(); | 363 ThreadUtils.assertOnUiThread(); |
544 // The context needs be Activity to create the ContentVideoView correctl
y. | 364 // The context needs be Activity to create the ContentVideoView correctl
y. |
545 if (!(context instanceof Activity)) { | 365 if (!(context instanceof Activity)) { |
546 Log.w(TAG, "Wrong type of context, can't create fullscreen video"); | 366 Log.w(TAG, "Wrong type of context, can't create fullscreen video"); |
547 return null; | 367 return null; |
548 } | 368 } |
549 return new ContentVideoView(context, nativeContentVideoView, client); | 369 if (legacy) { |
550 } | 370 return new ContentVideoViewLegacy(context, nativeContentVideoView, c
lient); |
551 | 371 } else { |
552 private void removeMediaController() { | 372 return new ContentVideoView(context, nativeContentVideoView, client)
; |
553 if (mMediaController != null) { | |
554 mMediaController.setEnabled(false); | |
555 mMediaController.hide(); | |
556 mMediaController = null; | |
557 } | 373 } |
558 } | 374 } |
559 | 375 |
560 public void removeSurfaceView() { | 376 public void removeSurfaceView() { |
561 removeView(mVideoSurfaceView); | 377 removeView(mVideoSurfaceView); |
562 removeView(mProgressView); | 378 removeView(mProgressView); |
563 mVideoSurfaceView = null; | 379 mVideoSurfaceView = null; |
564 mProgressView = null; | 380 mProgressView = null; |
565 } | 381 } |
566 | 382 |
567 public void exitFullscreen(boolean relaseMediaPlayer) { | 383 public void exitFullscreen(boolean relaseMediaPlayer) { |
568 destroyContentVideoView(false); | 384 destroyContentVideoView(false); |
569 if (mNativeContentVideoView != 0) { | 385 if (mNativeContentVideoView != 0) { |
570 nativeExitFullscreen(mNativeContentVideoView, relaseMediaPlayer); | 386 nativeExitFullscreen(mNativeContentVideoView, relaseMediaPlayer); |
571 mNativeContentVideoView = 0; | 387 mNativeContentVideoView = 0; |
572 } | 388 } |
573 } | 389 } |
574 | 390 |
| 391 @CalledByNative |
| 392 private void onExitFullscreen() { |
| 393 exitFullscreen(false); |
| 394 } |
| 395 |
575 /** | 396 /** |
576 * This method shall only be called by native and exitFullscreen, | 397 * This method shall only be called by native and exitFullscreen, |
577 * To exit fullscreen, use exitFullscreen in Java. | 398 * To exit fullscreen, use exitFullscreen in Java. |
578 */ | 399 */ |
579 @CalledByNative | 400 @CalledByNative |
580 private void destroyContentVideoView(boolean nativeViewDestroyed) { | 401 protected void destroyContentVideoView(boolean nativeViewDestroyed) { |
581 if (mVideoSurfaceView != null) { | 402 if (mVideoSurfaceView != null) { |
582 removeMediaController(); | |
583 removeSurfaceView(); | 403 removeSurfaceView(); |
584 setVisibility(View.GONE); | 404 setVisibility(View.GONE); |
585 | 405 |
586 // To prevent re-entrance, call this after removeSurfaceView. | 406 // To prevent re-entrance, call this after removeSurfaceView. |
587 mClient.onDestroyContentVideoView(); | 407 mClient.onDestroyContentVideoView(); |
588 } | 408 } |
589 if (nativeViewDestroyed) { | 409 if (nativeViewDestroyed) { |
590 mNativeContentVideoView = 0; | 410 mNativeContentVideoView = 0; |
591 } | 411 } |
592 } | 412 } |
593 | 413 |
594 public static ContentVideoView getContentVideoView() { | 414 public static ContentVideoView getContentVideoView() { |
595 return nativeGetSingletonJavaContentVideoView(); | 415 return nativeGetSingletonJavaContentVideoView(); |
596 } | 416 } |
597 | 417 |
598 @Override | 418 @Override |
599 public boolean onTouchEvent(MotionEvent ev) { | 419 public boolean onKeyUp(int keyCode, KeyEvent event) { |
600 return true; | 420 if (keyCode == KeyEvent.KEYCODE_BACK) { |
601 } | |
602 | |
603 @Override | |
604 public boolean onKeyDown(int keyCode, KeyEvent event) { | |
605 if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.AC
TION_UP) { | |
606 exitFullscreen(false); | 421 exitFullscreen(false); |
607 return true; | 422 return true; |
608 } | 423 } |
609 return super.onKeyDown(keyCode, event); | 424 return super.onKeyUp(keyCode, event); |
610 } | 425 } |
611 | 426 |
612 private static native ContentVideoView nativeGetSingletonJavaContentVideoVie
w(); | 427 private static native ContentVideoView nativeGetSingletonJavaContentVideoVie
w(); |
613 private native void nativeExitFullscreen(long nativeContentVideoView, | 428 private native void nativeExitFullscreen(long nativeContentVideoView, |
614 boolean relaseMediaPlayer); | 429 boolean relaseMediaPlayer); |
615 private native int nativeGetCurrentPosition(long nativeContentVideoView); | 430 private native int nativeGetCurrentPosition(long nativeContentVideoView); |
616 private native int nativeGetDurationInMilliSeconds(long nativeContentVideoVi
ew); | 431 private native int nativeGetDurationInMilliSeconds(long nativeContentVideoVi
ew); |
617 private native void nativeUpdateMediaMetadata(long nativeContentVideoView); | 432 private native void nativeUpdateMediaMetadata(long nativeContentVideoView); |
618 private native int nativeGetVideoWidth(long nativeContentVideoView); | 433 private native int nativeGetVideoWidth(long nativeContentVideoView); |
619 private native int nativeGetVideoHeight(long nativeContentVideoView); | 434 private native int nativeGetVideoHeight(long nativeContentVideoView); |
620 private native boolean nativeIsPlaying(long nativeContentVideoView); | 435 private native boolean nativeIsPlaying(long nativeContentVideoView); |
621 private native void nativePause(long nativeContentVideoView); | 436 private native void nativePause(long nativeContentVideoView); |
622 private native void nativePlay(long nativeContentVideoView); | 437 private native void nativePlay(long nativeContentVideoView); |
623 private native void nativeSeekTo(long nativeContentVideoView, int msec); | 438 private native void nativeSeekTo(long nativeContentVideoView, int msec); |
624 private native void nativeSetSurface(long nativeContentVideoView, Surface su
rface); | 439 private native void nativeSetSurface(long nativeContentVideoView, Surface su
rface); |
625 } | 440 } |
OLD | NEW |