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