HTML5VideoViewProxy.java revision 1a88acbed9cd04d7c8ddd0c33a15926238157a07
16fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu/*
26fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Copyright (C) 2009 The Android Open Source Project
36fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
46fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Licensed under the Apache License, Version 2.0 (the "License");
56fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * you may not use this file except in compliance with the License.
66fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * You may obtain a copy of the License at
76fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
86fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *      http://www.apache.org/licenses/LICENSE-2.0
96fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
106fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Unless required by applicable law or agreed to in writing, software
116fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * distributed under the License is distributed on an "AS IS" BASIS,
126fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * See the License for the specific language governing permissions and
146fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * limitations under the License.
156fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */
166fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
176fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescupackage android.webkit;
186fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
196fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.content.Context;
2064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.graphics.Bitmap;
2164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.graphics.BitmapFactory;
22661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.graphics.SurfaceTexture;
233c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescuimport android.media.MediaPlayer;
2464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.EventHandler;
2564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.Headers;
2664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.RequestHandle;
2764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.RequestQueue;
2864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.SslCertificate;
2964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.SslError;
306fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Handler;
316fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Looper;
326fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Message;
336fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.util.Log;
346fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
3564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport java.io.ByteArrayOutputStream;
3664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport java.io.IOException;
3742509799f261c844bf6be66ce630c47bdee620f3Ben Murdochimport java.net.MalformedURLException;
3842509799f261c844bf6be66ce630c47bdee620f3Ben Murdochimport java.net.URL;
396fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport java.util.HashMap;
40290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescuimport java.util.Map;
416fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
426fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu/**
433c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * <p>Proxy for HTML5 video views.
446fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */
45290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescuclass HTML5VideoViewProxy extends Handler
46290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                          implements MediaPlayer.OnPreparedListener,
4750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                          MediaPlayer.OnCompletionListener,
48661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                          MediaPlayer.OnErrorListener,
49c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                          MediaPlayer.OnInfoListener,
50661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                          SurfaceTexture.OnFrameAvailableListener {
516fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    // Logging tag.
526fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    private static final String LOGTAG = "HTML5VideoViewProxy";
536fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
543c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    // Message Ids for WebCore thread -> UI thread communication.
5550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int PLAY                = 100;
5650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int SEEK                = 101;
5750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int PAUSE               = 102;
5850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int ERROR               = 103;
5950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int LOAD_DEFAULT_POSTER = 104;
60c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    private static final int BUFFERING_START     = 105;
61c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    private static final int BUFFERING_END       = 106;
626fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
6364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // Message Ids to be handled on the WebCore thread
64290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int PREPARED          = 200;
65290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int ENDED             = 201;
6650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int POSTER_FETCHED    = 202;
6743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    private static final int PAUSED            = 203;
68b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu    private static final int STOPFULLSCREEN    = 204;
6964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
70048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    // Timer thread -> UI thread
71048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    private static final int TIMEUPDATE = 300;
72048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
73290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // The C++ MediaPlayerPrivateAndroid object.
74290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    int mNativePointer;
7564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The handler for WebCore thread messages;
7664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private Handler mWebCoreHandler;
773c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    // The WebView instance that created this view.
783c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    private WebView mWebView;
7964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The poster image to be shown when the video is not playing.
8050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    // This ref prevents the bitmap from being GC'ed.
8150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private Bitmap mPoster;
8264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The poster downloader.
8364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private PosterDownloader mPosterDownloader;
84290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // The seek position.
85290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private int mSeekPosition;
8664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // A helper class to control the playback. This executes on the UI thread!
8764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private static final class VideoPlayer {
8864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The proxy that is currently playing (if any).
8964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static HTML5VideoViewProxy mCurrentProxy;
9064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The VideoView instance. This is a singleton for now, at least until
9164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // http://b/issue?id=1973663 is fixed.
92661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        private static HTML5VideoView mHTML5VideoView;
93048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
94661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        private static boolean isVideoSelfEnded = false;
95661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // By using the baseLayer and the current video Layer ID, we can
96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // identify the exact layer on the UI thread to use the SurfaceTexture.
97661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        private static int mBaseLayer = 0;
98661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
99f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu        private static void setPlayerBuffering(boolean playerBuffering) {
100f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu            mHTML5VideoView.setPlayerBuffering(playerBuffering);
101f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu        }
102f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu
103661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // Every time webView setBaseLayer, this will be called.
104661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When we found the Video layer, then we set the Surface Texture to it.
105661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // Otherwise, we may want to delete the Surface Texture to save memory.
106661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        public static void setBaseLayer(int layer) {
10710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            // Don't do this for full screen mode.
10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            if (mHTML5VideoView != null
1093fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu                && !mHTML5VideoView.isFullScreenMode()
1103fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu                && !mHTML5VideoView.surfaceTextureDeleted()) {
111661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mBaseLayer = layer;
112661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
113661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
1143fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu                SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(currentVideoLayerId);
1153fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu                int textureName = mHTML5VideoView.getTextureName();
1163fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu
117661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) {
118265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                    int playerState = mHTML5VideoView.getCurrentState();
119f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu                    if (mHTML5VideoView.getPlayerBuffering())
120c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                        playerState = HTML5VideoView.STATE_NOTPREPARED;
121661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    boolean foundInTree = nativeSendSurfaceTexture(surfTexture,
122661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                            layer, currentVideoLayerId, textureName,
123265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                            playerState);
1241e26d82ffaf983dc288152cfe8c0a821de33f2a4Teng-Hui Zhu                    if (playerState >= HTML5VideoView.STATE_PREPARED
125265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                            && !foundInTree) {
126661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                        mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
127661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                        mHTML5VideoView.deleteSurfaceTexture();
12831d2aa1e17f1ee580edb762a6ef634098bba02bbAndrei Popescu                    }
12964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
130661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            }
131661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
132661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
133661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When a WebView is paused, we also want to pause the video in it.
134661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        public static void pauseAndDispatch() {
135661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mHTML5VideoView != null) {
136661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
137661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // When switching out, clean the video content on the old page
138661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // by telling the layer not readyToUseSurfTex.
139661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                setBaseLayer(mBaseLayer);
140661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            }
141661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
14264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
14310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public static void enterFullScreenVideo(int layerId, String url,
14410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                HTML5VideoViewProxy proxy, WebView webView) {
14510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // Save the inline video info and inherit it in the full screen
14610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                int savePosition = 0;
14710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                boolean savedIsPlaying = false;
14810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                if (mHTML5VideoView != null) {
14910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    // If we are playing the same video, then it is better to
15010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    // save the current position.
15110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    if (layerId == mHTML5VideoView.getVideoLayerId()) {
15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                        savePosition = mHTML5VideoView.getCurrentPosition();
15310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                        savedIsPlaying = mHTML5VideoView.isPlaying();
15410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    }
15510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    mHTML5VideoView.release();
15710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                }
15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(),
15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                        layerId, savePosition, savedIsPlaying);
16010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mCurrentProxy = proxy;
16110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.setVideoURI(url, mCurrentProxy);
16310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
16410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView);
16510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
16610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
167661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // This is on the UI thread.
168661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When native tell Java to play, we need to check whether or not it is
169661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // still the same video by using videoLayerId and treat it differently.
170290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void play(String url, int time, HTML5VideoViewProxy proxy,
171661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                WebChromeClient client, int videoLayerId) {
172661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            int currentVideoLayerId = -1;
17310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            boolean backFromFullScreenMode = false;
17410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            if (mHTML5VideoView != null) {
175661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
1761a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu                backFromFullScreenMode = mHTML5VideoView.fullScreenExited();
17710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            }
178661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
17910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            if (backFromFullScreenMode
1803fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu                || currentVideoLayerId != videoLayerId
1813fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu                || mHTML5VideoView.surfaceTextureDeleted()) {
182661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // Here, we handle the case when switching to a new video,
183661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // either inside a WebView or across WebViews
184661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // For switching videos within a WebView or across the WebView,
185661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // we need to pause the old one and re-create a new media player
186661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // inside the HTML5VideoView.
187661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (mHTML5VideoView != null) {
18822954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu                    if (!backFromFullScreenMode) {
18922954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu                        mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
19022954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu                    }
191661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    // release the media player to avoid finalize error
192661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mHTML5VideoView.release();
193a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu                }
194661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mCurrentProxy = proxy;
19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, false);
196a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu
19710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.setVideoURI(url, mCurrentProxy);
19810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.prepareDataAndDisplayMode(proxy);
199661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            } else if (mCurrentProxy == proxy) {
200661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // Here, we handle the case when we keep playing with one video
201661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (!mHTML5VideoView.isPlaying()) {
202661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mHTML5VideoView.seekTo(time);
203661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mHTML5VideoView.start();
204661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                }
205661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            } else if (mCurrentProxy != null) {
20610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // Some other video is already playing. Notify the caller that
20710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // its playback ended.
208661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                proxy.dispatchOnEnded();
209bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu            }
21064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
211290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
212048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        public static boolean isPlaying(HTML5VideoViewProxy proxy) {
213661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            return (mCurrentProxy == proxy && mHTML5VideoView != null
214661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    && mHTML5VideoView.isPlaying());
215048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        }
216048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
217048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        public static int getCurrentPosition() {
218048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            int currentPosMs = 0;
219661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mHTML5VideoView != null) {
220661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                currentPosMs = mHTML5VideoView.getCurrentPosition();
221048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            }
222048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            return currentPosMs;
223048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        }
224048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
225290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void seek(int time, HTML5VideoViewProxy proxy) {
226661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mCurrentProxy == proxy && time >= 0 && mHTML5VideoView != null) {
227661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mHTML5VideoView.seekTo(time);
228290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
229290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        }
230290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
231290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void pause(HTML5VideoViewProxy proxy) {
232661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mCurrentProxy == proxy && mHTML5VideoView != null) {
233661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mHTML5VideoView.pause();
234290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
235290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        }
236bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu
237bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu        public static void onPrepared() {
2380504967cb05f7bbd0c17962360a5d88ace8d173fTeng-Hui Zhu            if (!mHTML5VideoView.isFullScreenMode() || mHTML5VideoView.getAutostart()) {
2390504967cb05f7bbd0c17962360a5d88ace8d173fTeng-Hui Zhu                mHTML5VideoView.start();
2400504967cb05f7bbd0c17962360a5d88ace8d173fTeng-Hui Zhu            }
241265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            if (mBaseLayer != 0) {
242265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                setBaseLayer(mBaseLayer);
243265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            }
244661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
245661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
246661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        public static void end() {
247661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mCurrentProxy != null) {
248661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (isVideoSelfEnded)
249661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mCurrentProxy.dispatchOnEnded();
250661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                else
251661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mCurrentProxy.dispatchOnPaused();
252661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            }
253661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            isVideoSelfEnded = false;
254bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu        }
255290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
256290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
257290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // A bunch event listeners for our VideoView
258290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // MediaPlayer.OnPreparedListener
259290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void onPrepared(MediaPlayer mp) {
260bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu        VideoPlayer.onPrepared();
261290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message msg = Message.obtain(mWebCoreHandler, PREPARED);
262290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Map<String, Object> map = new HashMap<String, Object>();
263290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("dur", new Integer(mp.getDuration()));
264290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("width", new Integer(mp.getVideoWidth()));
265290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("height", new Integer(mp.getVideoHeight()));
266290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        msg.obj = map;
267290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mWebCoreHandler.sendMessage(msg);
268290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
269290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
270290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // MediaPlayer.OnCompletionListener;
271290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void onCompletion(MediaPlayer mp) {
272c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu        // The video ended by itself, so we need to
273c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu        // send a message to the UI thread to dismiss
274c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu        // the video view and to return to the WebView.
27543aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang        // arg1 == 1 means the video ends by itself.
27643aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang        sendMessage(obtainMessage(ENDED, 1, 0));
277290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
278290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
27950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    // MediaPlayer.OnErrorListener
28050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    public boolean onError(MediaPlayer mp, int what, int extra) {
28150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        sendMessage(obtainMessage(ERROR));
28250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        return false;
28350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    }
28450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu
285c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu    public void dispatchOnEnded() {
286290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message msg = Message.obtain(mWebCoreHandler, ENDED);
287290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mWebCoreHandler.sendMessage(msg);
28864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
2893c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
29043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    public void dispatchOnPaused() {
291b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu        Message msg = Message.obtain(mWebCoreHandler, PAUSED);
292b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu        mWebCoreHandler.sendMessage(msg);
293b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu    }
294b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu
295b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu    public void dispatchOnStopFullScreen() {
296b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu        Message msg = Message.obtain(mWebCoreHandler, STOPFULLSCREEN);
297b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu        mWebCoreHandler.sendMessage(msg);
29843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    }
29943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang
300048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    public void onTimeupdate() {
301048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        sendMessage(obtainMessage(TIMEUPDATE));
302048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    }
303048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
304661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // When there is a frame ready from surface texture, we should tell WebView
305661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // to refresh.
306661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    @Override
307661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
308661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // TODO: This should support partial invalidation too.
309661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mWebView.invalidate();
310661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
311661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
312048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    // Handler for the messages from WebCore or Timer thread to the UI thread.
31364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    @Override
31464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public void handleMessage(Message msg) {
31564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // This executes on the UI thread.
31664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        switch (msg.what) {
31764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            case PLAY: {
31864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                String url = (String) msg.obj;
31964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                WebChromeClient client = mWebView.getWebChromeClient();
320661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                int videoLayerID = msg.arg1;
32164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (client != null) {
322661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    VideoPlayer.play(url, mSeekPosition, this, client, videoLayerID);
32364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
32464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                break;
32564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
326290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            case SEEK: {
327290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                Integer time = (Integer) msg.obj;
328290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                mSeekPosition = time;
329290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                VideoPlayer.seek(mSeekPosition, this);
330290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                break;
331290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
332290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            case PAUSE: {
333290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                VideoPlayer.pause(this);
334290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                break;
335290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
33646a83b4ead517b9fc13b4bee4c59c3eaf4d3fdd9Andrei Popescu            case ENDED:
33743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                if (msg.arg1 == 1)
33843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                    VideoPlayer.isVideoSelfEnded = true;
339661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                VideoPlayer.end();
340661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                break;
34150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            case ERROR: {
34250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                WebChromeClient client = mWebView.getWebChromeClient();
34350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                if (client != null) {
34450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    client.onHideCustomView();
34550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                }
34650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                break;
34750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            }
34850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            case LOAD_DEFAULT_POSTER: {
34950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                WebChromeClient client = mWebView.getWebChromeClient();
35050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                if (client != null) {
35150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    doSetPoster(client.getDefaultVideoPoster());
35250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                }
35350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                break;
35450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            }
355048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            case TIMEUPDATE: {
356048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                if (VideoPlayer.isPlaying(this)) {
357048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                    sendTimeupdate();
358048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                }
359048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                break;
360048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            }
361c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            case BUFFERING_START: {
362f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu                VideoPlayer.setPlayerBuffering(true);
363c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                break;
364c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            }
365c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            case BUFFERING_END: {
366f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu                VideoPlayer.setPlayerBuffering(false);
367c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                break;
368c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            }
36964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
37064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
37164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
37264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // Everything below this comment executes on the WebCore thread, except for
37364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // the EventHandler methods, which are called on the network thread.
37464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
37564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // A helper class that knows how to download posters
37664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private static final class PosterDownloader implements EventHandler {
37764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The request queue. This is static as we have one queue for all posters.
37864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static RequestQueue mRequestQueue;
37964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static int mQueueRefCount = 0;
38064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The poster URL
38142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch        private URL mUrl;
38264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The proxy we're doing this for.
38364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private final HTML5VideoViewProxy mProxy;
38464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The poster bytes. We only touch this on the network thread.
38564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private ByteArrayOutputStream mPosterBytes;
38664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The request handle. We only touch this on the WebCore thread.
38764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private RequestHandle mRequestHandle;
38864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The response status code.
38964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private int mStatusCode;
39064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The response headers.
39164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private Headers mHeaders;
39264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The handler to handle messages on the WebCore thread.
39364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private Handler mHandler;
39464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
39564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public PosterDownloader(String url, HTML5VideoViewProxy proxy) {
39642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            try {
39742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                mUrl = new URL(url);
39842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            } catch (MalformedURLException e) {
39942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                mUrl = null;
40042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            }
40164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mProxy = proxy;
40264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mHandler = new Handler();
40364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
40464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Start the download. Called on WebCore thread.
40564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void start() {
40664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            retainQueue();
40742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch
40842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            if (mUrl == null) {
40942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                return;
41042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            }
41142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch
41242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            // Only support downloading posters over http/https.
41342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            // FIXME: Add support for other schemes. WebKit seems able to load
41442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            // posters over other schemes e.g. file://, but gets the dimensions wrong.
41542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            String protocol = mUrl.getProtocol();
41642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            if ("http".equals(protocol) || "https".equals(protocol)) {
41742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                mRequestHandle = mRequestQueue.queueRequest(mUrl.toString(), "GET", null,
41842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                        this, null, 0);
41942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            }
42064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
42164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel the download if active and release the queue. Called on WebCore thread.
42264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void cancelAndReleaseQueue() {
42364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mRequestHandle != null) {
42464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestHandle.cancel();
42564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestHandle = null;
42664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
42764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            releaseQueue();
42864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
42964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // EventHandler methods. Executed on the network thread.
43064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void status(int major_version,
43164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                int minor_version,
43264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                int code,
43364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                String reason_phrase) {
43464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mStatusCode = code;
43564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
4363c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
43764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void headers(Headers headers) {
43864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mHeaders = headers;
4393c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4403c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
44164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void data(byte[] data, int len) {
44264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mPosterBytes == null) {
44364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mPosterBytes = new ByteArrayOutputStream();
4443c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
44564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterBytes.write(data, 0, len);
4463c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4473c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
44864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void endData() {
44964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mStatusCode == 200) {
45064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (mPosterBytes.size() > 0) {
45164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    Bitmap poster = BitmapFactory.decodeByteArray(
45264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                            mPosterBytes.toByteArray(), 0, mPosterBytes.size());
45350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    mProxy.doSetPoster(poster);
45464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
45564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                cleanup();
45664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            } else if (mStatusCode >= 300 && mStatusCode < 400) {
45764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                // We have a redirect.
45842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                try {
45942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                    mUrl = new URL(mHeaders.getLocation());
46042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                } catch (MalformedURLException e) {
46142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                    mUrl = null;
46242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                }
46364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (mUrl != null) {
46464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mHandler.post(new Runnable() {
46564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                       public void run() {
46664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                           if (mRequestHandle != null) {
46742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                               mRequestHandle.setupRedirect(mUrl.toString(), mStatusCode,
46864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                                       new HashMap<String, String>());
46964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                           }
47064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                       }
47164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    });
47264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
47364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
4743c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4753c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
47664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void certificate(SslCertificate certificate) {
47764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // Don't care.
4783c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4793c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
48064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void error(int id, String description) {
48164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            cleanup();
48264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
48364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
48464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public boolean handleSslErrorRequest(SslError error) {
48564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // Don't care. If this happens, data() will never be called so
48664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // mPosterBytes will never be created, so no need to call cleanup.
48764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return false;
48864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
48964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Tears down the poster bytes stream. Called on network thread.
49064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void cleanup() {
49164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mPosterBytes != null) {
49264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                try {
49364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mPosterBytes.close();
49464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                } catch (IOException ignored) {
49564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // Ignored.
49664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                } finally {
49764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mPosterBytes = null;
49864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
4993c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
50064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
50164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
50264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Queue management methods. Called on WebCore thread.
50364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void retainQueue() {
50464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mRequestQueue == null) {
50564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue = new RequestQueue(mProxy.getContext());
5063c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
50764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mQueueRefCount++;
5083c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
5093c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
51064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void releaseQueue() {
51164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mQueueRefCount == 0) {
51264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                return;
51364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
51464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (--mQueueRefCount == 0) {
51564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue.shutdown();
51664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue = null;
51764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
5183c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
5193c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    }
5206fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
5216fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
5226fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * Private constructor.
523290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param webView is the WebView that hosts the video.
524290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object.
5256fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
526290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private HTML5VideoViewProxy(WebView webView, int nativePtr) {
5276fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        // This handler is for the main (UI) thread.
5286fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        super(Looper.getMainLooper());
5293c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        // Save the WebView object.
5303c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        mWebView = webView;
531661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // Pass Proxy into webview, such that every time we have a setBaseLayer
532661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // call, we tell this Proxy to call the native to update the layer tree
533661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // for the Video Layer's surface texture info
534661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mWebView.setHTML5VideoViewProxy(this);
535290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        // Save the native ptr
536290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mNativePointer = nativePtr;
53764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // create the message handler for this thread
53864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        createWebCoreHandler();
5396fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
5406fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
54164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private void createWebCoreHandler() {
54264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mWebCoreHandler = new Handler() {
54364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            @Override
54464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            public void handleMessage(Message msg) {
54564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                switch (msg.what) {
546290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    case PREPARED: {
547290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Map<String, Object> map = (Map<String, Object>) msg.obj;
548290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer duration = (Integer) map.get("dur");
549290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer width = (Integer) map.get("width");
550290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer height = (Integer) map.get("height");
551290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        nativeOnPrepared(duration.intValue(), width.intValue(),
552290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                                height.intValue(), mNativePointer);
553290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        break;
554290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    }
555290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    case ENDED:
556ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch                        mSeekPosition = 0;
557290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        nativeOnEnded(mNativePointer);
558290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        break;
55943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                    case PAUSED:
56043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                        nativeOnPaused(mNativePointer);
56143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                        break;
56250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    case POSTER_FETCHED:
56350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                        Bitmap poster = (Bitmap) msg.obj;
56450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                        nativeOnPosterFetched(poster, mNativePointer);
56550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                        break;
566048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                    case TIMEUPDATE:
567048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                        nativeOnTimeupdate(msg.arg1, mNativePointer);
568048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                        break;
569b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu                    case STOPFULLSCREEN:
570b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu                        nativeOnStopFullscreen(mNativePointer);
571b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu                        break;
5723c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu                }
57364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
57464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        };
57564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
57664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
57764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private void doSetPoster(Bitmap poster) {
57864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (poster == null) {
57964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
5806fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        }
58150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        // Save a ref to the bitmap and send it over to the WebCore thread.
58250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        mPoster = poster;
58350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        Message msg = Message.obtain(mWebCoreHandler, POSTER_FETCHED);
58450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        msg.obj = poster;
58550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        mWebCoreHandler.sendMessage(msg);
5866fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
5876fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
588048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    private void sendTimeupdate() {
589048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        Message msg = Message.obtain(mWebCoreHandler, TIMEUPDATE);
590048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        msg.arg1 = VideoPlayer.getCurrentPosition();
591048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        mWebCoreHandler.sendMessage(msg);
592048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    }
593048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
59464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public Context getContext() {
59564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        return mWebView.getContext();
59664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
59764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
59864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The public methods below are all called from WebKit only.
5996fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
6006fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * Play a video stream.
6016fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * @param url is the URL of the video stream.
6026fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
603661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void play(String url, int position, int videoLayerID) {
60464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (url == null) {
60564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
60664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
607ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch
608ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch        if (position > 0) {
609ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch            seek(position);
610ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch        }
6116fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        Message message = obtainMessage(PLAY);
612661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        message.arg1 = videoLayerID;
61364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        message.obj = url;
6146fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        sendMessage(message);
6156fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
6166fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
61764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
618290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * Seek into the video stream.
619290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param  time is the position in the video stream.
620290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     */
621290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void seek(int time) {
622290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message message = obtainMessage(SEEK);
623290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        message.obj = new Integer(time);
624290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        sendMessage(message);
625290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
626290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
627290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    /**
628290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * Pause the playback.
629290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     */
630290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void pause() {
631290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message message = obtainMessage(PAUSE);
632290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        sendMessage(message);
633290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
634290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
635290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    /**
63650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu     * Tear down this proxy object.
63764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
63850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    public void teardown() {
63964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // This is called by the C++ MediaPlayerPrivate dtor.
64064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel any active poster download.
64164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (mPosterDownloader != null) {
64264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterDownloader.cancelAndReleaseQueue();
64364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
64450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        mNativePointer = 0;
64564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
64664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
64764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
64864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * Load the poster image.
64964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * @param url is the URL of the poster image.
65064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
65164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public void loadPoster(String url) {
65264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (url == null) {
65350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            Message message = obtainMessage(LOAD_DEFAULT_POSTER);
65450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            sendMessage(message);
65564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
65664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
65764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel any active poster download.
65864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (mPosterDownloader != null) {
65964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterDownloader.cancelAndReleaseQueue();
66064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
66164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Load the poster asynchronously
66264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mPosterDownloader = new PosterDownloader(url, this);
66364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mPosterDownloader.start();
6640a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott    }
6650a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott
66610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // These three function are called from UI thread only by WebView.
667661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setBaseLayer(int layer) {
668661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        VideoPlayer.setBaseLayer(layer);
669661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
670661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
671661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void pauseAndDispatch() {
672661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        VideoPlayer.pauseAndDispatch();
673661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
67410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
67510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void enterFullScreenVideo(int layerId, String url) {
67610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        VideoPlayer.enterFullScreenVideo(layerId, url, this, mWebView);
67710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
67810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
6796fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
6803c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu     * The factory for HTML5VideoViewProxy instances.
6816fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * @param webViewCore is the WebViewCore that is requesting the proxy.
6826fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     *
6833c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu     * @return a new HTML5VideoViewProxy object.
6846fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
685290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public static HTML5VideoViewProxy getInstance(WebViewCore webViewCore, int nativePtr) {
686290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr);
6876fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
688290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
6891708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch    /* package */ WebView getWebView() {
6901708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch        return mWebView;
6911708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch    }
6921708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch
693290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private native void nativeOnPrepared(int duration, int width, int height, int nativePointer);
694290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private native void nativeOnEnded(int nativePointer);
69543aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    private native void nativeOnPaused(int nativePointer);
69650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private native void nativeOnPosterFetched(Bitmap poster, int nativePointer);
697048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    private native void nativeOnTimeupdate(int position, int nativePointer);
698b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu    private native void nativeOnStopFullscreen(int nativePointer);
699661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture,
700661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            int baseLayer, int videoLayerId, int textureName,
701265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            int playerState);
702c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu
703c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    @Override
704c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    public boolean onInfo(MediaPlayer mp, int what, int extra) {
705c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
706c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            sendMessage(obtainMessage(BUFFERING_START, what, extra));
707c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
708c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            sendMessage(obtainMessage(BUFFERING_END, what, extra));
709c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        }
710c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        return false;
711c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    }
7126fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu}
713