1778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu/* 2778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * Copyright (C) 2012 The Android Open Source Project 3778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * 4778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 5778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * you may not use this file except in compliance with the License. 6778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * You may obtain a copy of the License at 7778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * 8778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * http://www.apache.org/licenses/LICENSE-2.0 9778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * 10778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software 11778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * distributed under the License is distributed on an "AS IS" BASIS, 12778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * See the License for the specific language governing permissions and 14778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * limitations under the License. 15778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu */ 1610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 1710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhupackage android.webkit; 1810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 1910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.content.Context; 2010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.media.MediaPlayer; 2110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.media.Metadata; 2210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.Gravity; 2310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.MotionEvent; 2410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.SurfaceHolder; 2510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.SurfaceView; 2610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.View; 2710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.ViewGroup; 2810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.widget.FrameLayout; 2910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.widget.MediaController; 3010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.widget.MediaController.MediaPlayerControl; 3110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 3210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 3310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu/** 3410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu * @hide This is only used by the browser 3510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu */ 3610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhupublic class HTML5VideoFullScreen extends HTML5VideoView 3710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu implements MediaPlayerControl, MediaPlayer.OnPreparedListener, 3810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu View.OnTouchListener { 3910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 401ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu // Add this sub-class to handle the resizing when rotating screen. 411ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu private class VideoSurfaceView extends SurfaceView { 421ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu 431ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu public VideoSurfaceView(Context context) { 441ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu super(context); 451ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu } 461ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu 471ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu @Override 481ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 491ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu int width = getDefaultSize(mVideoWidth, widthMeasureSpec); 501ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu int height = getDefaultSize(mVideoHeight, heightMeasureSpec); 511ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu if (mVideoWidth > 0 && mVideoHeight > 0) { 521ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu if ( mVideoWidth * height > width * mVideoHeight ) { 531ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu height = width * mVideoHeight / mVideoWidth; 541ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu } else if ( mVideoWidth * height < width * mVideoHeight ) { 551ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu width = height * mVideoWidth / mVideoHeight; 561ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu } 571ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu } 581ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu setMeasuredDimension(width, height); 591ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu } 601ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu } 611ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu 621ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu // This view will contain the video. 631ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu private VideoSurfaceView mVideoSurfaceView; 6410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 6510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // We need the full screen state to decide which surface to render to and 6610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // when to create the MediaPlayer accordingly. 6710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu static final int FULLSCREEN_OFF = 0; 6810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu static final int FULLSCREEN_SURFACECREATING = 1; 6910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu static final int FULLSCREEN_SURFACECREATED = 2; 7010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 7110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private int mFullScreenMode; 7210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // The Media Controller only used for full screen mode 7310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private MediaController mMediaController; 7410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 7510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // SurfaceHolder for full screen 7610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private SurfaceHolder mSurfaceHolder = null; 7710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 7810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Data only for MediaController 7910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private boolean mCanSeekBack; 8010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private boolean mCanSeekForward; 8110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private boolean mCanPause; 8210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private int mCurrentBufferPercentage; 8310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 8410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // The progress view. 8510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private static View mProgressView; 8610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // The container for the progress view and video view 8710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private static FrameLayout mLayout; 8810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 891ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu // The video size will be ready when prepared. Used to make sure the aspect 901ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu // ratio is correct. 911ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu private int mVideoWidth; 921ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu private int mVideoHeight; 93c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu private boolean mPlayingWhenDestroyed = false; 9410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() 9510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu { 965558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu @Override 9710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void surfaceChanged(SurfaceHolder holder, int format, 9810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu int w, int h) 9910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu { 10010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mPlayer != null && mMediaController != null 10110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu && mCurrentState == STATE_PREPARED) { 10210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mMediaController.isShowing()) { 10310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // ensure the controller will get repositioned later 10410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mMediaController.hide(); 10510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 10610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mMediaController.show(); 10710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 10910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 1105558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu @Override 11110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void surfaceCreated(SurfaceHolder holder) 11210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu { 11310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mSurfaceHolder = holder; 11410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mFullScreenMode = FULLSCREEN_SURFACECREATED; 11510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 11610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu prepareForFullScreen(); 11710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 11810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 1195558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu @Override 12010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void surfaceDestroyed(SurfaceHolder holder) 12110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu { 122c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mPlayingWhenDestroyed = mPlayer.isPlaying(); 123ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu pauseAndDispatch(mProxy); 124c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu // We need to set the display to null before switching into inline 125c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu // mode to avoid error. 126c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mPlayer.setDisplay(null); 127ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu mSurfaceHolder = null; 128ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu if (mMediaController != null) { 129ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu mMediaController.hide(); 130ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu } 13110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 13210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu }; 13310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 1345a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = 1355a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu new MediaPlayer.OnVideoSizeChangedListener() { 1365a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu @Override 1375a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 1385a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu mVideoWidth = mp.getVideoWidth(); 1395a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu mVideoHeight = mp.getVideoHeight(); 1405a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu if (mVideoWidth != 0 && mVideoHeight != 0) { 1415a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight); 1425a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu } 1435a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu } 1445a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu }; 1455a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu 1461ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu private SurfaceView getSurfaceView() { 1471ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu return mVideoSurfaceView; 14810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 14910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 150c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu HTML5VideoFullScreen(Context context, int videoLayerId, int position, boolean skipPrepare) { 1511ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoSurfaceView = new VideoSurfaceView(context); 15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mFullScreenMode = FULLSCREEN_OFF; 1531ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoWidth = 0; 1541ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoHeight = 0; 155c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu init(videoLayerId, position, skipPrepare); 15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 15710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private void setMediaController(MediaController m) { 15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mMediaController = m; 16010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu attachMediaController(); 16110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 16310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private void attachMediaController() { 16410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mPlayer != null && mMediaController != null) { 16510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mMediaController.setMediaPlayer(this); 1661ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mMediaController.setAnchorView(mVideoSurfaceView); 16710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu //Will be enabled when prepared 16810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mMediaController.setEnabled(false); 16910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 17110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 17210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 17310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void decideDisplayMode() { 17410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mPlayer.setDisplay(mSurfaceHolder); 17510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 17610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 1771ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu private void prepareForFullScreen() { 178c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb MediaController mc = new FullScreenMediaController(mProxy.getContext(), mLayout); 179d763c2cbe8d9e7eb2a83ba00c5c33f226bd02122Marco Nelissen mc.setSystemUiVisibility(mLayout.getSystemUiVisibility()); 180d763c2cbe8d9e7eb2a83ba00c5c33f226bd02122Marco Nelissen setMediaController(mc); 1812deec6651c5fc2f479a7d594cad00e36edf73eafTeng-Hui Zhu mPlayer.setScreenOnWhilePlaying(true); 1825a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu mPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); 18310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu prepareDataAndDisplayMode(mProxy); 18410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 18510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 18610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 18710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private void toggleMediaControlsVisiblity() { 18810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mMediaController.isShowing()) { 18910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mMediaController.hide(); 19010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } else { 19110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mMediaController.show(); 19210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 19310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 19410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 19610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void onPrepared(MediaPlayer mp) { 19710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu super.onPrepared(mp); 19810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 1991ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoSurfaceView.setOnTouchListener(this); 20010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Get the capabilities of the player for this stream 20110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL, 20210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu MediaPlayer.BYPASS_METADATA_FILTER); 20310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (data != null) { 20410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCanPause = !data.has(Metadata.PAUSE_AVAILABLE) 20510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu || data.getBoolean(Metadata.PAUSE_AVAILABLE); 20610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE) 20710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE); 20810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE) 20910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE); 21010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } else { 21110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCanPause = mCanSeekBack = mCanSeekForward = true; 21210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 21310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 21496fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu if (getStartWhenPrepared()) { 21596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mPlayer.start(); 2166a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu // Clear the flag. 2176a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu setStartWhenPrepared(false); 2186a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu } 2196a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu 2206a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu // mMediaController status depends on the Metadata result, so put it 2216a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu // after reading the MetaData. 2226a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu // And make sure mPlayer state is updated before showing the controller. 2236a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu if (mMediaController != null) { 2246a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu mMediaController.setEnabled(true); 2256a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu mMediaController.show(); 22696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu } 227c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu 228c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu if (mProgressView != null) { 229c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mProgressView.setVisibility(View.GONE); 230c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } 231c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu 232c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mVideoWidth = mp.getVideoWidth(); 233c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mVideoHeight = mp.getVideoHeight(); 234c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu // This will trigger the onMeasure to get the display size right. 235c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight); 236c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu 23710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 23810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 2395558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu @Override 2401a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu public boolean fullScreenExited() { 2411a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu return (mLayout == null); 2421a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu } 24310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 24410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private final WebChromeClient.CustomViewCallback mCallback = 24510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu new WebChromeClient.CustomViewCallback() { 2465558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu @Override 24710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void onCustomViewHidden() { 24810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // It listens to SurfaceHolder.Callback.SurfaceDestroyed event 24910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // which happens when the video view is detached from its parent 25010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // view. This happens in the WebChromeClient before this method 25110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // is invoked. 25210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mLayout.removeView(getSurfaceView()); 25310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 25410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mProgressView != null) { 25510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mLayout.removeView(mProgressView); 25610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mProgressView = null; 25710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 25810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mLayout = null; 25910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Re enable plugin views. 26010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mProxy.getWebView().getViewManager().showAll(); 261b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu // Don't show the controller after exiting the full screen. 262b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu mMediaController = null; 263c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu // Continue the inline mode playing if necessary. 264c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mProxy.dispatchOnStopFullScreen(mPlayingWhenDestroyed); 265c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mProxy = null; 26610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 26710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu }; 26810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 26910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 27010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void enterFullScreenVideoState(int layerId, 2713c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon HTML5VideoViewProxy proxy, WebViewClassic webView) { 27210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mFullScreenMode = FULLSCREEN_SURFACECREATING; 27310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCurrentBufferPercentage = 0; 27410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); 27510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mProxy = proxy; 27610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 2771ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoSurfaceView.getHolder().addCallback(mSHCallback); 2781ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 2791ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoSurfaceView.setFocusable(true); 2801ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoSurfaceView.setFocusableInTouchMode(true); 2811ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu mVideoSurfaceView.requestFocus(); 2825558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu mVideoSurfaceView.setOnKeyListener(mProxy); 28310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Create a FrameLayout that will contain the VideoView and the 28410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // progress view (if any). 28510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mLayout = new FrameLayout(mProxy.getContext()); 28610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( 28710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu ViewGroup.LayoutParams.WRAP_CONTENT, 28810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu ViewGroup.LayoutParams.WRAP_CONTENT, 28910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu Gravity.CENTER); 29010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 29110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mLayout.addView(getSurfaceView(), layoutParams); 29210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 29310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mLayout.setVisibility(View.VISIBLE); 29410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu WebChromeClient client = webView.getWebChromeClient(); 295592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu if (client != null) { 296592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu client.onShowCustomView(mLayout, mCallback); 297592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu // Plugins like Flash will draw over the video so hide 298592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu // them while we're playing. 299592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu if (webView.getViewManager() != null) 300592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu webView.getViewManager().hideAll(); 301592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu 302592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu mProgressView = client.getVideoLoadingProgressView(); 303592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu if (mProgressView != null) { 304592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu mLayout.addView(mProgressView, layoutParams); 305592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu mProgressView.setVisibility(View.VISIBLE); 306592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu } 30710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 30810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 30910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 31010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu /** 31110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu * @return true when we are in full screen mode, even the surface not fully 31210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu * created. 31310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu */ 3145558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu @Override 31510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public boolean isFullScreenMode() { 31610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return true; 31710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 31810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 31910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // MediaController FUNCTIONS: 32010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 32110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public boolean canPause() { 32210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return mCanPause; 32310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 32410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 32510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 32610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public boolean canSeekBackward() { 32710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return mCanSeekBack; 32810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 32910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 33010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 33110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public boolean canSeekForward() { 33210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return mCanSeekForward; 33310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 33410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 33510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 33610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public int getBufferPercentage() { 33710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mPlayer != null) { 33810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return mCurrentBufferPercentage; 33910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 34010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return 0; 34110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 34210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 3434dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu @Override 3444dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu public void showControllerInFullScreen() { 345422400f92d56d42bb234c7f9407a00b3bc836907Teng-Hui Zhu if (mMediaController != null) { 346422400f92d56d42bb234c7f9407a00b3bc836907Teng-Hui Zhu mMediaController.show(0); 347422400f92d56d42bb234c7f9407a00b3bc836907Teng-Hui Zhu } 3484dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu } 3494dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu 35010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Other listeners functions: 35110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = 35210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu new MediaPlayer.OnBufferingUpdateListener() { 3535558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu @Override 35410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void onBufferingUpdate(MediaPlayer mp, int percent) { 35510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCurrentBufferPercentage = percent; 35610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 35710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu }; 35810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 35910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 36010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public boolean onTouch(View v, MotionEvent event) { 36110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mFullScreenMode >= FULLSCREEN_SURFACECREATED 36210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu && mMediaController != null) { 36310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu toggleMediaControlsVisiblity(); 36410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 36510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return false; 36610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 36710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 368f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu @Override 369f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu protected void switchProgressView(boolean playerBuffering) { 3702302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu if (mProgressView != null) { 3712302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu if (playerBuffering) { 3722302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu mProgressView.setVisibility(View.VISIBLE); 3732302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu } else { 3742302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu mProgressView.setVisibility(View.GONE); 3752302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu } 376f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu } 377f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu return; 378f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu } 379c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb 380c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb static class FullScreenMediaController extends MediaController { 381c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb 382c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb View mVideoView; 383c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb 384c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb public FullScreenMediaController(Context context, View video) { 385c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb super(context); 386c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb mVideoView = video; 387c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb } 388c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb 389c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb @Override 390c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb public void show() { 391c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb super.show(); 392c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb if (mVideoView != null) { 393c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); 394c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb } 395c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb } 396c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb 397c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb @Override 398c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb public void hide() { 399c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb if (mVideoView != null) { 400c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE 401c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 402c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb } 403c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb super.hide(); 404c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb } 405c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb 406c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb } 407c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb 40810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu} 409