| 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 |