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 */ 16661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 17661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhupackage android.webkit; 18661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 19661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.media.MediaPlayer; 2064855da755e74676af49b3c7ece338acd72b2f3cTeng-Hui Zhuimport android.net.Uri; 21661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.webkit.HTML5VideoViewProxy; 22661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport java.io.IOException; 2310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.HashMap; 24661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport java.util.Map; 2510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.Timer; 2610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.TimerTask; 27661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 28661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu/** 29661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu * @hide This is only used by the browser 30661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu */ 31a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhupublic class HTML5VideoView implements MediaPlayer.OnPreparedListener { 32661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 3310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected static final String LOGTAG = "HTML5VideoView"; 3410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 3510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected static final String COOKIE = "Cookie"; 3610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected static final String HIDE_URL_LOGS = "x-hide-urls-from-log"; 37661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 38661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // For handling the seekTo before prepared, we need to know whether or not 39661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // the video is prepared. Therefore, we differentiate the state between 40661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // prepared and not prepared. 41661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When the video is not prepared, we will have to save the seekTo time, 42661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // and use it when prepared to play. 43265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu // NOTE: these values are in sync with VideoLayerAndroid.h in webkit side. 44265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu // Please keep them in sync when changed. 45265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu static final int STATE_INITIALIZED = 0; 46c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu static final int STATE_PREPARING = 1; 47265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu static final int STATE_PREPARED = 2; 48265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu static final int STATE_PLAYING = 3; 49c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu static final int STATE_RESETTED = 4; 50156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu static final int STATE_RELEASED = 5; 51661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 5210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected HTML5VideoViewProxy mProxy; 53661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 54661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Save the seek time when not prepared. This can happen when switching 55661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // video besides initial load. 5610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected int mSaveSeekTime; 57661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 58661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // This is used to find the VideoLayer on the native side. 5910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected int mVideoLayerId; 60661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 61c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu // Given the fact we only have one SurfaceTexture, we cannot support multiple 62c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu // player at the same time. We may recreate a new one and abandon the old 63c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu // one at transition time. 64c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu protected static MediaPlayer mPlayer = null; 65c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu protected static int mCurrentState = -1; 6610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 6710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // We need to save such info. 6864855da755e74676af49b3c7ece338acd72b2f3cTeng-Hui Zhu protected Uri mUri; 6910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected Map<String, String> mHeaders; 70661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 7110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // The timer for timeupate events. 7210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate 7310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected static Timer mTimer; 74661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 75c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu protected boolean mPauseDuringPreparing; 76c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu 7710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // The spec says the timer should fire every 250 ms or less. 7810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private static final int TIMEUPDATE_PERIOD = 250; // ms 79c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu private boolean mSkipPrepare = false; 8010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 8110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // common Video control FUNCTIONS: 82661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void start() { 83661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentState == STATE_PREPARED) { 84cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu // When replaying the same video, there is no onPrepared call. 85cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu // Therefore, the timer should be set up here. 86cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu if (mTimer == null) 87cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu { 88cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu mTimer = new Timer(); 89cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu mTimer.schedule(new TimeupdateTask(mProxy), TIMEUPDATE_PERIOD, 90cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu TIMEUPDATE_PERIOD); 91cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu } 92661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mPlayer.start(); 932fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu setPlayerBuffering(false); 94661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 95661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 97661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void pause() { 98b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu if (isPlaying()) { 9910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mPlayer.pause(); 100c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } else if (mCurrentState == STATE_PREPARING) { 101158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu mPauseDuringPreparing = true; 10210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 103cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu // Delete the Timer to stop it since there is no stop call. 10410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mTimer != null) { 10510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mTimer.purge(); 106cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu mTimer.cancel(); 107cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu mTimer = null; 10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 109661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 110661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 111661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public int getDuration() { 11210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mCurrentState == STATE_PREPARED) { 11310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return mPlayer.getDuration(); 11410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } else { 11510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return -1; 11610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 117661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 119661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public int getCurrentPosition() { 12010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mCurrentState == STATE_PREPARED) { 12110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return mPlayer.getCurrentPosition(); 12210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 12310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return 0; 124661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 125661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 126661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void seekTo(int pos) { 127661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentState == STATE_PREPARED) 128661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mPlayer.seekTo(pos); 129661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu else 130661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mSaveSeekTime = pos; 131661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 132661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 133661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public boolean isPlaying() { 134b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu if (mCurrentState == STATE_PREPARED) { 135b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu return mPlayer.isPlaying(); 136b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu } else { 137b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu return false; 138b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu } 139661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 140661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 141c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu public void reset() { 142156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu if (mCurrentState < STATE_RESETTED) { 143c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mPlayer.reset(); 144b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu } 145c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mCurrentState = STATE_RESETTED; 146661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 147661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 148661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void stopPlayback() { 14910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mCurrentState == STATE_PREPARED) { 15010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mPlayer.stop(); 15110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 152661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 153661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 154156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu public static void release() { 155156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu if (mPlayer != null && mCurrentState != STATE_RELEASED) { 156156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu mPlayer.release(); 157156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu mPlayer = null; 158156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu } 159156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu mCurrentState = STATE_RELEASED; 160156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu } 161156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu 162156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu public boolean isReleased() { 163156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu return mCurrentState == STATE_RELEASED; 164156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu } 165156f97b6c8580b790600b09b679b9dab8b271c5dTeng-Hui Zhu 166158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu public boolean getPauseDuringPreparing() { 167158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu return mPauseDuringPreparing; 168158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu } 169158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu 17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Every time we start a new Video, we create a VideoView and a MediaPlayer 171c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu public void init(int videoLayerId, int position, boolean skipPrepare) { 172c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu if (mPlayer == null) { 173c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mPlayer = new MediaPlayer(); 174c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mCurrentState = STATE_INITIALIZED; 175c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } 176c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mSkipPrepare = skipPrepare; 177c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu // If we want to skip the prepare, then we keep the state. 178c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu if (!mSkipPrepare) { 179c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mCurrentState = STATE_INITIALIZED; 180c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } 181661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mProxy = null; 182661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mVideoLayerId = videoLayerId; 18310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mSaveSeekTime = position; 184cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu mTimer = null; 185158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu mPauseDuringPreparing = false; 186661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 187661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 18810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected HTML5VideoView() { 189661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 190661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 19110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu protected static Map<String, String> generateHeaders(String url, 19210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu HTML5VideoViewProxy proxy) { 19310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu boolean isPrivate = proxy.getWebView().isPrivateBrowsingEnabled(); 19410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate); 19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu Map<String, String> headers = new HashMap<String, String>(); 19610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (cookieValue != null) { 19710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu headers.put(COOKIE, cookieValue); 19810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 19910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (isPrivate) { 20010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu headers.put(HIDE_URL_LOGS, "true"); 20110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 202661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 20310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return headers; 204661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 205661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 20610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void setVideoURI(String uri, HTML5VideoViewProxy proxy) { 207661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When switching players, surface texture will be reused. 20864855da755e74676af49b3c7ece338acd72b2f3cTeng-Hui Zhu mUri = Uri.parse(uri); 20910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHeaders = generateHeaders(uri, proxy); 210661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 211661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 212661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Listeners setup FUNCTIONS: 213661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void setOnCompletionListener(HTML5VideoViewProxy proxy) { 214661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mPlayer.setOnCompletionListener(proxy); 215661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 216661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 217661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void setOnErrorListener(HTML5VideoViewProxy proxy) { 218661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mPlayer.setOnErrorListener(proxy); 219661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 220661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 221661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void setOnPreparedListener(HTML5VideoViewProxy proxy) { 222661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mProxy = proxy; 223661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mPlayer.setOnPreparedListener(this); 224661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 225661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 226a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu public void setOnInfoListener(HTML5VideoViewProxy proxy) { 227a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu mPlayer.setOnInfoListener(proxy); 228a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu } 229a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu 23096fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu public void prepareDataCommon(HTML5VideoViewProxy proxy) { 231c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu if (!mSkipPrepare) { 232c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu try { 233c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mPlayer.reset(); 234c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders); 235c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mPlayer.prepareAsync(); 236c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } catch (IllegalArgumentException e) { 237c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu e.printStackTrace(); 238c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } catch (IllegalStateException e) { 239c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu e.printStackTrace(); 240c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } catch (IOException e) { 241c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu e.printStackTrace(); 242c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } 243c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mCurrentState = STATE_PREPARING; 244c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } else { 245c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu // If we skip prepare and the onPrepared happened in inline mode, we 246c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu // don't need to call prepare again, we just need to call onPrepared 247c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu // to refresh the state here. 248c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu if (mCurrentState >= STATE_PREPARED) { 249c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu onPrepared(mPlayer); 250c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } 251c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mSkipPrepare = false; 252661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 253661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 254661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 25596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu public void reprepareData(HTML5VideoViewProxy proxy) { 25696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mPlayer.reset(); 25796fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu prepareDataCommon(proxy); 25896fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu } 25996fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 26096fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // Normally called immediately after setVideoURI. But for full screen, 26196fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // this should be after surface holder created 26296fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) { 26396fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // SurfaceTexture will be created lazily here for inline mode 26496fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu decideDisplayMode(); 26596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 26696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu setOnCompletionListener(proxy); 26796fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu setOnPreparedListener(proxy); 26896fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu setOnErrorListener(proxy); 26996fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu setOnInfoListener(proxy); 27096fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 27196fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu prepareDataCommon(proxy); 27296fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu } 27396fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 274661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 27510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Common code 276661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public int getVideoLayerId() { 277661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu return mVideoLayerId; 278661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 279661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 280265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu 281265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu public int getCurrentState() { 282b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu if (isPlaying()) { 283265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu return STATE_PLAYING; 284265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu } else { 285265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu return mCurrentState; 286265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu } 287265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu } 288265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu 28910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private static final class TimeupdateTask extends TimerTask { 29010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu private HTML5VideoViewProxy mProxy; 291661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 29210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public TimeupdateTask(HTML5VideoViewProxy proxy) { 29310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mProxy = proxy; 29410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 29510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 29610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu @Override 29710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void run() { 29810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mProxy.onTimeupdate(); 29910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 300661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 301661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 302661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu @Override 303661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void onPrepared(MediaPlayer mp) { 304661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentState = STATE_PREPARED; 305661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu seekTo(mSaveSeekTime); 306cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu if (mProxy != null) { 307661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mProxy.onPrepared(mp); 308cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu } 309158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu if (mPauseDuringPreparing) { 310158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu pauseAndDispatch(mProxy); 311158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu mPauseDuringPreparing = false; 312158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu } 313661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 314661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 315661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Pause the play and update the play/pause button 316661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void pauseAndDispatch(HTML5VideoViewProxy proxy) { 317158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu pause(); 318158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu if (proxy != null) { 319158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu proxy.dispatchOnPaused(); 320661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 32110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 32210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 32310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Below are functions that are different implementation on inline and full- 32410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // screen mode. Some are specific to one type, but currently are called 32510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // directly from the proxy. 32610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void enterFullScreenVideoState(int layerId, 3273c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon HTML5VideoViewProxy proxy, WebViewClassic webView) { 32810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 32910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 33010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public boolean isFullScreenMode() { 33110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return false; 33210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 33310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 33410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void decideDisplayMode() { 33510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 33610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 33710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public boolean getReadyToUseSurfTex() { 33810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return false; 33910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 34010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 34110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void deleteSurfaceTexture() { 34210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 34310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 34410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public int getTextureName() { 34510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu return 0; 346661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 347661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 3482fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu // This is true only when the player is buffering and paused 3492fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu public boolean mPlayerBuffering = false; 3502fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu 3512fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu public boolean getPlayerBuffering() { 3522fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu return mPlayerBuffering; 3532fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu } 3542fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu 3552fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu public void setPlayerBuffering(boolean playerBuffering) { 3562fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu mPlayerBuffering = playerBuffering; 3572fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu switchProgressView(playerBuffering); 3582fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu } 3592fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu 3602fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu 3612fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu protected void switchProgressView(boolean playerBuffering) { 3622fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu // Only used in HTML5VideoFullScreen 3632fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu } 3642fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu 3651a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu public boolean fullScreenExited() { 3661a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu // Only meaningful for HTML5VideoFullScreen 3671a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu return false; 3681a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu } 3691a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu 370c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu private boolean mStartWhenPrepared = false; 37196fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 37296fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu public void setStartWhenPrepared(boolean willPlay) { 373c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mStartWhenPrepared = willPlay; 37496fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu } 37596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 37696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu public boolean getStartWhenPrepared() { 377c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu return mStartWhenPrepared; 37896fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu } 37996fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 3804dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu public void showControllerInFullScreen() { 3814dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu } 3824dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu 383661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu} 384