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