HTML5VideoViewProxy.java revision 96fae5e088916e1da8d4afaf40758ceec6e7187a
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; 69e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu private static final int RESTORESTATE = 205; 7064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 71048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Timer thread -> UI thread 72048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private static final int TIMEUPDATE = 300; 73048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 74290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The C++ MediaPlayerPrivateAndroid object. 75290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu int mNativePointer; 7664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler for WebCore thread messages; 7764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mWebCoreHandler; 783c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // The WebView instance that created this view. 793c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu private WebView mWebView; 8064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster image to be shown when the video is not playing. 8150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // This ref prevents the bitmap from being GC'ed. 8250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private Bitmap mPoster; 8364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster downloader. 8464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private PosterDownloader mPosterDownloader; 85290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The seek position. 86290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private int mSeekPosition; 8764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class to control the playback. This executes on the UI thread! 8864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class VideoPlayer { 8964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy that is currently playing (if any). 9064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static HTML5VideoViewProxy mCurrentProxy; 9164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The VideoView instance. This is a singleton for now, at least until 9264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // http://b/issue?id=1973663 is fixed. 93661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static HTML5VideoView mHTML5VideoView; 94048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 95661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static boolean isVideoSelfEnded = false; 96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // By using the baseLayer and the current video Layer ID, we can 97661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // identify the exact layer on the UI thread to use the SurfaceTexture. 98661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static int mBaseLayer = 0; 99661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 100f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu private static void setPlayerBuffering(boolean playerBuffering) { 101f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu mHTML5VideoView.setPlayerBuffering(playerBuffering); 102f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu } 103f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu 104661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Every time webView setBaseLayer, this will be called. 105661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When we found the Video layer, then we set the Surface Texture to it. 106661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Otherwise, we may want to delete the Surface Texture to save memory. 107661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void setBaseLayer(int layer) { 10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Don't do this for full screen mode. 10910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null 1103fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu && !mHTML5VideoView.isFullScreenMode() 1113fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu && !mHTML5VideoView.surfaceTextureDeleted()) { 112661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mBaseLayer = layer; 113661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 114661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 1153fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(currentVideoLayerId); 1163fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu int textureName = mHTML5VideoView.getTextureName(); 1173fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu 118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) { 119265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState = mHTML5VideoView.getCurrentState(); 120f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu if (mHTML5VideoView.getPlayerBuffering()) 121c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu playerState = HTML5VideoView.STATE_NOTPREPARED; 122661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu boolean foundInTree = nativeSendSurfaceTexture(surfTexture, 123661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu layer, currentVideoLayerId, textureName, 124265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu playerState); 1251e26d82ffaf983dc288152cfe8c0a821de33f2a4Teng-Hui Zhu if (playerState >= HTML5VideoView.STATE_PREPARED 126265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu && !foundInTree) { 127661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 128661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.deleteSurfaceTexture(); 12931d2aa1e17f1ee580edb762a6ef634098bba02bbAndrei Popescu } 13064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 131661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 132661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 133661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 134661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When a WebView is paused, we also want to pause the video in it. 135661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void pauseAndDispatch() { 136661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 137661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 138661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When switching out, clean the video content on the old page 139661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // by telling the layer not readyToUseSurfTex. 140661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu setBaseLayer(mBaseLayer); 141661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 142661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 14364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 14410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public static void enterFullScreenVideo(int layerId, String url, 14510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu HTML5VideoViewProxy proxy, WebView webView) { 14610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Save the inline video info and inherit it in the full screen 14710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu int savePosition = 0; 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 } 15410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.release(); 15510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(), 157e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu layerId, savePosition); 15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCurrentProxy = proxy; 15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 16010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 16110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView); 16310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 16410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 165d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu public static void exitFullScreenVideo(HTML5VideoViewProxy proxy, 166d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu WebView webView) { 167d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu if (!mHTML5VideoView.fullScreenExited() && mHTML5VideoView.isFullScreenMode()) { 168d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu WebChromeClient client = webView.getWebChromeClient(); 169d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu if (client != null) { 170d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu client.onHideCustomView(); 171d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 172d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 173d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 174d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu 175661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // This is on the UI thread. 176661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When native tell Java to play, we need to check whether or not it is 177661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // still the same video by using videoLayerId and treat it differently. 178290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void play(String url, int time, HTML5VideoViewProxy proxy, 179661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu WebChromeClient client, int videoLayerId) { 180661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = -1; 18110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu boolean backFromFullScreenMode = false; 18210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null) { 183661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 1841a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu backFromFullScreenMode = mHTML5VideoView.fullScreenExited(); 18596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 18696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // When playing video back to back in full screen mode, 18796fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // javascript will switch the src and call play. 18896fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // In this case, we can just reuse the same full screen view, 18996fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // and play the video after prepared. 19096fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu if (mHTML5VideoView.isFullScreenMode() 19196fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu && !backFromFullScreenMode 19296fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu && currentVideoLayerId != videoLayerId 19396fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu && mCurrentProxy != proxy) { 19496fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mCurrentProxy = proxy; 19596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mHTML5VideoView.setStartWhenPrepared(true); 19696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mHTML5VideoView.setVideoURI(url, proxy); 19796fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mHTML5VideoView.reprepareData(proxy); 19896fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu return; 19996fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu } 20010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 201661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 20210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (backFromFullScreenMode 2033fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu || currentVideoLayerId != videoLayerId 2043fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu || mHTML5VideoView.surfaceTextureDeleted()) { 205661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when switching to a new video, 206661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // either inside a WebView or across WebViews 207661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // For switching videos within a WebView or across the WebView, 208661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // we need to pause the old one and re-create a new media player 209661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // inside the HTML5VideoView. 210661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 21122954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu if (!backFromFullScreenMode) { 21222954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 21322954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu } 214661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // release the media player to avoid finalize error 215661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.release(); 216a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu } 217661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy = proxy; 218e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu mHTML5VideoView = new HTML5VideoInline(videoLayerId, time); 219a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu 22010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 22110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.prepareDataAndDisplayMode(proxy); 222661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } else if (mCurrentProxy == proxy) { 223661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when we keep playing with one video 224661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (!mHTML5VideoView.isPlaying()) { 225661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 226661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.start(); 227661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 228661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } else if (mCurrentProxy != null) { 22910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Some other video is already playing. Notify the caller that 23010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // its playback ended. 231661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu proxy.dispatchOnEnded(); 232bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 23364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 234290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 235048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static boolean isPlaying(HTML5VideoViewProxy proxy) { 236661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu return (mCurrentProxy == proxy && mHTML5VideoView != null 237661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu && mHTML5VideoView.isPlaying()); 238048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 239048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 240048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static int getCurrentPosition() { 241048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu int currentPosMs = 0; 242661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 243661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentPosMs = mHTML5VideoView.getCurrentPosition(); 244048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 245048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu return currentPosMs; 246048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 247048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 248290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void seek(int time, HTML5VideoViewProxy proxy) { 249661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && time >= 0 && mHTML5VideoView != null) { 250661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 251290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 252290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 253290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 254290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void pause(HTML5VideoViewProxy proxy) { 255661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && mHTML5VideoView != null) { 256661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pause(); 257290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 258290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 259bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu 260bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu public static void onPrepared() { 261e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu if (!mHTML5VideoView.isFullScreenMode()) { 2620504967cb05f7bbd0c17962360a5d88ace8d173fTeng-Hui Zhu mHTML5VideoView.start(); 2630504967cb05f7bbd0c17962360a5d88ace8d173fTeng-Hui Zhu } 264265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu if (mBaseLayer != 0) { 265265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu setBaseLayer(mBaseLayer); 266265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu } 267661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 268661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 269661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void end() { 270661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy != null) { 271661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (isVideoSelfEnded) 272661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnEnded(); 273661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu else 274661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnPaused(); 275661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 276661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu isVideoSelfEnded = false; 277bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 278290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 279290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 280290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // A bunch event listeners for our VideoView 281290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnPreparedListener 282290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onPrepared(MediaPlayer mp) { 283bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu VideoPlayer.onPrepared(); 284290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, PREPARED); 285290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = new HashMap<String, Object>(); 286290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("dur", new Integer(mp.getDuration())); 287290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("width", new Integer(mp.getVideoWidth())); 288290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("height", new Integer(mp.getVideoHeight())); 289290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu msg.obj = map; 290290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 291290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 292290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 293290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnCompletionListener; 294290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onCompletion(MediaPlayer mp) { 295c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // The video ended by itself, so we need to 296c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // send a message to the UI thread to dismiss 297c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // the video view and to return to the WebView. 29843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang // arg1 == 1 means the video ends by itself. 29943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang sendMessage(obtainMessage(ENDED, 1, 0)); 300290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 301290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 30250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // MediaPlayer.OnErrorListener 30350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public boolean onError(MediaPlayer mp, int what, int extra) { 30450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(obtainMessage(ERROR)); 30550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu return false; 30650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 30750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu 308c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu public void dispatchOnEnded() { 309290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, ENDED); 310290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 31164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 3123c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 31343aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang public void dispatchOnPaused() { 314b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu Message msg = Message.obtain(mWebCoreHandler, PAUSED); 315b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu mWebCoreHandler.sendMessage(msg); 316b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu } 317b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu 318b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu public void dispatchOnStopFullScreen() { 319b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu Message msg = Message.obtain(mWebCoreHandler, STOPFULLSCREEN); 320b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu mWebCoreHandler.sendMessage(msg); 32143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang } 32243aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang 323e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu public void dispatchOnRestoreState() { 324e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu Message msg = Message.obtain(mWebCoreHandler, RESTORESTATE); 325e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu mWebCoreHandler.sendMessage(msg); 326e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu } 327e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu 328048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public void onTimeupdate() { 329048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendMessage(obtainMessage(TIMEUPDATE)); 330048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 331048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 332661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When there is a frame ready from surface texture, we should tell WebView 333661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // to refresh. 334661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu @Override 335661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void onFrameAvailable(SurfaceTexture surfaceTexture) { 336661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // TODO: This should support partial invalidation too. 337661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.invalidate(); 338661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 339661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 340048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Handler for the messages from WebCore or Timer thread to the UI thread. 34164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 34264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 34364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This executes on the UI thread. 34464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 34564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu case PLAY: { 34664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String url = (String) msg.obj; 34764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 348661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int videoLayerID = msg.arg1; 34964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (client != null) { 350661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.play(url, mSeekPosition, this, client, videoLayerID); 35164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 35264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu break; 35364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 354290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case SEEK: { 355290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer time = (Integer) msg.obj; 356290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mSeekPosition = time; 357290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.seek(mSeekPosition, this); 358290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 359290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 360290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PAUSE: { 361290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.pause(this); 362290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 363290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 36446a83b4ead517b9fc13b4bee4c59c3eaf4d3fdd9Andrei Popescu case ENDED: 36543aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang if (msg.arg1 == 1) 36643aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang VideoPlayer.isVideoSelfEnded = true; 367661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.end(); 368661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu break; 36950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case ERROR: { 37050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 37150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 37250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu client.onHideCustomView(); 37350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 37450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 37550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 37650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case LOAD_DEFAULT_POSTER: { 37750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 37850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 37950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu doSetPoster(client.getDefaultVideoPoster()); 38050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 38150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 38250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 383048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: { 384048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu if (VideoPlayer.isPlaying(this)) { 385048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendTimeupdate(); 386048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 387048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 388048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 389c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu case BUFFERING_START: { 390f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu VideoPlayer.setPlayerBuffering(true); 391c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu break; 392c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 393c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu case BUFFERING_END: { 394f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu VideoPlayer.setPlayerBuffering(false); 395c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu break; 396c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 39764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 39864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 39964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 40064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Everything below this comment executes on the WebCore thread, except for 40164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // the EventHandler methods, which are called on the network thread. 40264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 40364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class that knows how to download posters 40464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class PosterDownloader implements EventHandler { 40564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request queue. This is static as we have one queue for all posters. 40664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static RequestQueue mRequestQueue; 40764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static int mQueueRefCount = 0; 40864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster URL 40942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch private URL mUrl; 41064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy we're doing this for. 41164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private final HTML5VideoViewProxy mProxy; 41264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster bytes. We only touch this on the network thread. 41364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private ByteArrayOutputStream mPosterBytes; 41464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request handle. We only touch this on the WebCore thread. 41564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private RequestHandle mRequestHandle; 41664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response status code. 41764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private int mStatusCode; 41864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response headers. 41964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Headers mHeaders; 42064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler to handle messages on the WebCore thread. 42164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mHandler; 42264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 42364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public PosterDownloader(String url, HTML5VideoViewProxy proxy) { 42442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 42542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(url); 42642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 42742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 42842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 42964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mProxy = proxy; 43064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler = new Handler(); 43164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 43264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Start the download. Called on WebCore thread. 43364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void start() { 43464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu retainQueue(); 43542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 43642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if (mUrl == null) { 43742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch return; 43842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 43942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 44042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // Only support downloading posters over http/https. 44142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // FIXME: Add support for other schemes. WebKit seems able to load 44242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // posters over other schemes e.g. file://, but gets the dimensions wrong. 44342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch String protocol = mUrl.getProtocol(); 44442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if ("http".equals(protocol) || "https".equals(protocol)) { 44542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle = mRequestQueue.queueRequest(mUrl.toString(), "GET", null, 44642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch this, null, 0); 44742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 44864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 44964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel the download if active and release the queue. Called on WebCore thread. 45064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void cancelAndReleaseQueue() { 45164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 45264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle.cancel(); 45364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle = null; 45464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 45564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu releaseQueue(); 45664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 45764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // EventHandler methods. Executed on the network thread. 45864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void status(int major_version, 45964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int minor_version, 46064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int code, 46164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String reason_phrase) { 46264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mStatusCode = code; 46364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4643c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 46564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void headers(Headers headers) { 46664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHeaders = headers; 4673c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4683c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 46964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void data(byte[] data, int len) { 47064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes == null) { 47164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = new ByteArrayOutputStream(); 4723c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 47364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.write(data, 0, len); 4743c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4753c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 47664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void endData() { 47764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mStatusCode == 200) { 47864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes.size() > 0) { 47964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu Bitmap poster = BitmapFactory.decodeByteArray( 48064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.toByteArray(), 0, mPosterBytes.size()); 48150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mProxy.doSetPoster(poster); 48264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 48364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 48464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } else if (mStatusCode >= 300 && mStatusCode < 400) { 48564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // We have a redirect. 48642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 48742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(mHeaders.getLocation()); 48842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 48942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 49042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 49164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mUrl != null) { 49264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler.post(new Runnable() { 49364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void run() { 49464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 49542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle.setupRedirect(mUrl.toString(), mStatusCode, 49664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu new HashMap<String, String>()); 49764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 49864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 49964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }); 50064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 50164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 5023c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5033c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 50464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void certificate(SslCertificate certificate) { 50564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. 5063c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5073c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 50864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void error(int id, String description) { 50964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 51064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 51164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 51264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public boolean handleSslErrorRequest(SslError error) { 51364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. If this happens, data() will never be called so 51464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // mPosterBytes will never be created, so no need to call cleanup. 51564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return false; 51664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 51764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Tears down the poster bytes stream. Called on network thread. 51864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void cleanup() { 51964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes != null) { 52064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu try { 52164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.close(); 52264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } catch (IOException ignored) { 52364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Ignored. 52464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } finally { 52564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = null; 52664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 5273c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 52864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 52964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 53064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Queue management methods. Called on WebCore thread. 53164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void retainQueue() { 53264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestQueue == null) { 53364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = new RequestQueue(mProxy.getContext()); 5343c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 53564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mQueueRefCount++; 5363c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5373c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 53864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void releaseQueue() { 53964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mQueueRefCount == 0) { 54064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 54164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 54264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (--mQueueRefCount == 0) { 54364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue.shutdown(); 54464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = null; 54564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 5463c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5473c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5486fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 5496fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 5506fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Private constructor. 551290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param webView is the WebView that hosts the video. 552290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object. 5536fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 554290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private HTML5VideoViewProxy(WebView webView, int nativePtr) { 5556fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu // This handler is for the main (UI) thread. 5566fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu super(Looper.getMainLooper()); 5573c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // Save the WebView object. 5583c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu mWebView = webView; 559661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Pass Proxy into webview, such that every time we have a setBaseLayer 560661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // call, we tell this Proxy to call the native to update the layer tree 561661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // for the Video Layer's surface texture info 562661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.setHTML5VideoViewProxy(this); 563290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // Save the native ptr 564290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mNativePointer = nativePtr; 56564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // create the message handler for this thread 56664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu createWebCoreHandler(); 5676fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 5686fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 56964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void createWebCoreHandler() { 57064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mWebCoreHandler = new Handler() { 57164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 57264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 57364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 574290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PREPARED: { 575290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = (Map<String, Object>) msg.obj; 576290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer duration = (Integer) map.get("dur"); 577290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer width = (Integer) map.get("width"); 578290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer height = (Integer) map.get("height"); 579290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnPrepared(duration.intValue(), width.intValue(), 580290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu height.intValue(), mNativePointer); 581290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 582290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 583290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case ENDED: 584ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch mSeekPosition = 0; 585290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnEnded(mNativePointer); 586290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 58743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang case PAUSED: 58843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang nativeOnPaused(mNativePointer); 58943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang break; 59050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case POSTER_FETCHED: 59150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Bitmap poster = (Bitmap) msg.obj; 59250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu nativeOnPosterFetched(poster, mNativePointer); 59350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 594048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: 595048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu nativeOnTimeupdate(msg.arg1, mNativePointer); 596048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 597b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu case STOPFULLSCREEN: 598b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu nativeOnStopFullscreen(mNativePointer); 599b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu break; 600e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu case RESTORESTATE: 601e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu nativeOnRestoreState(mNativePointer); 602e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu break; 6033c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 60464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 60564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }; 60664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 60764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 60864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void doSetPoster(Bitmap poster) { 60964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (poster == null) { 61064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 6116fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 61250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // Save a ref to the bitmap and send it over to the WebCore thread. 61350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mPoster = poster; 61450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, POSTER_FETCHED); 61550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu msg.obj = poster; 61650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mWebCoreHandler.sendMessage(msg); 6176fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 6186fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 619048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private void sendTimeupdate() { 620048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, TIMEUPDATE); 621048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu msg.arg1 = VideoPlayer.getCurrentPosition(); 622048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu mWebCoreHandler.sendMessage(msg); 623048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 624048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 62564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public Context getContext() { 62664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return mWebView.getContext(); 62764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 62864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 62964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The public methods below are all called from WebKit only. 6306fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 6316fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Play a video stream. 6326fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param url is the URL of the video stream. 6336fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 634661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void play(String url, int position, int videoLayerID) { 63564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 63664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 63764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 638ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch 639ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch if (position > 0) { 640ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch seek(position); 641ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch } 6426fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu Message message = obtainMessage(PLAY); 643661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu message.arg1 = videoLayerID; 64464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu message.obj = url; 6456fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu sendMessage(message); 6466fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 6476fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 64864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 649290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Seek into the video stream. 650290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param time is the position in the video stream. 651290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 652290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void seek(int time) { 653290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(SEEK); 654290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu message.obj = new Integer(time); 655290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 656290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 657290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 658290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 659290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Pause the playback. 660290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 661290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void pause() { 662290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(PAUSE); 663290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 664290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 665290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 666290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 66750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu * Tear down this proxy object. 66864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 66950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public void teardown() { 67064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This is called by the C++ MediaPlayerPrivate dtor. 67164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 67264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 67364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 67464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 67550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mNativePointer = 0; 67664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 67764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 67864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 67964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * Load the poster image. 68064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * @param url is the URL of the poster image. 68164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 68264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void loadPoster(String url) { 68364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 68450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message message = obtainMessage(LOAD_DEFAULT_POSTER); 68550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(message); 68664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 68764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 68864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 68964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 69064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 69164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 69264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Load the poster asynchronously 69364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader = new PosterDownloader(url, this); 69464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.start(); 6950a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott } 6960a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott 69710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // These three function are called from UI thread only by WebView. 698661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void setBaseLayer(int layer) { 699661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.setBaseLayer(layer); 700661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 701661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 702661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void pauseAndDispatch() { 703661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.pauseAndDispatch(); 704661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 70510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 70610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void enterFullScreenVideo(int layerId, String url) { 70710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu VideoPlayer.enterFullScreenVideo(layerId, url, this, mWebView); 70810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 70910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 710d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu public void exitFullScreenVideo() { 711d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu VideoPlayer.exitFullScreenVideo(this, mWebView); 712d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 713d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu 7146fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 7153c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * The factory for HTML5VideoViewProxy instances. 7166fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param webViewCore is the WebViewCore that is requesting the proxy. 7176fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * 7183c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * @return a new HTML5VideoViewProxy object. 7196fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 720290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static HTML5VideoViewProxy getInstance(WebViewCore webViewCore, int nativePtr) { 721290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr); 7226fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 723290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 7241708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch /* package */ WebView getWebView() { 7251708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch return mWebView; 7261708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch } 7271708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch 728290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnPrepared(int duration, int width, int height, int nativePointer); 729290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnEnded(int nativePointer); 73043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang private native void nativeOnPaused(int nativePointer); 73150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private native void nativeOnPosterFetched(Bitmap poster, int nativePointer); 732048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private native void nativeOnTimeupdate(int position, int nativePointer); 733b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu private native void nativeOnStopFullscreen(int nativePointer); 734e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu private native void nativeOnRestoreState(int nativePointer); 735661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture, 736661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int baseLayer, int videoLayerId, int textureName, 737265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState); 738c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu 739c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu @Override 740c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu public boolean onInfo(MediaPlayer mp, int what, int extra) { 741c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) { 742c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu sendMessage(obtainMessage(BUFFERING_START, what, extra)); 743c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) { 744c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu sendMessage(obtainMessage(BUFFERING_END, what, extra)); 745c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 746c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu return false; 747c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 7486fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu} 749