HTML5VideoViewProxy.java revision f4d4e9e05f7605118910739c16e493e2ab869aae
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; 6864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 69048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Timer thread -> UI thread 70048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private static final int TIMEUPDATE = 300; 71048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 72290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The C++ MediaPlayerPrivateAndroid object. 73290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu int mNativePointer; 7464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler for WebCore thread messages; 7564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mWebCoreHandler; 763c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // The WebView instance that created this view. 773c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu private WebView mWebView; 7864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster image to be shown when the video is not playing. 7950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // This ref prevents the bitmap from being GC'ed. 8050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private Bitmap mPoster; 8164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster downloader. 8264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private PosterDownloader mPosterDownloader; 83290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The seek position. 84290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private int mSeekPosition; 8564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class to control the playback. This executes on the UI thread! 8664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class VideoPlayer { 8764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy that is currently playing (if any). 8864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static HTML5VideoViewProxy mCurrentProxy; 8964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The VideoView instance. This is a singleton for now, at least until 9064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // http://b/issue?id=1973663 is fixed. 91661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static HTML5VideoView mHTML5VideoView; 92048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 93661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static boolean isVideoSelfEnded = false; 94661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // By using the baseLayer and the current video Layer ID, we can 95661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // identify the exact layer on the UI thread to use the SurfaceTexture. 96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static int mBaseLayer = 0; 97661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 98f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu private static void setPlayerBuffering(boolean playerBuffering) { 99f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu mHTML5VideoView.setPlayerBuffering(playerBuffering); 100f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu } 101f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu 102661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Every time webView setBaseLayer, this will be called. 103661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When we found the Video layer, then we set the Surface Texture to it. 104661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Otherwise, we may want to delete the Surface Texture to save memory. 105661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void setBaseLayer(int layer) { 10610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Don't do this for full screen mode. 10710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null 10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu && !mHTML5VideoView.isFullScreenMode()) { 109661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mBaseLayer = layer; 110661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(); 111661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int textureName = mHTML5VideoView.getTextureName(); 112661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 113661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 114661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) { 115265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState = mHTML5VideoView.getCurrentState(); 116f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu if (mHTML5VideoView.getPlayerBuffering()) 117c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu playerState = HTML5VideoView.STATE_NOTPREPARED; 118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu boolean foundInTree = nativeSendSurfaceTexture(surfTexture, 119661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu layer, currentVideoLayerId, textureName, 120265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu playerState); 1211e26d82ffaf983dc288152cfe8c0a821de33f2a4Teng-Hui Zhu if (playerState >= HTML5VideoView.STATE_PREPARED 122265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu && !foundInTree) { 123661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 124661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.deleteSurfaceTexture(); 12531d2aa1e17f1ee580edb762a6ef634098bba02bbAndrei Popescu } 12664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 127661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 128661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 129661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 130661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When a WebView is paused, we also want to pause the video in it. 131661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void pauseAndDispatch() { 132661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 133661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 134661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When switching out, clean the video content on the old page 135661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // by telling the layer not readyToUseSurfTex. 136661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu setBaseLayer(mBaseLayer); 137661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 138661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 13964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 14010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public static void enterFullScreenVideo(int layerId, String url, 14110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu HTML5VideoViewProxy proxy, WebView webView) { 14210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Save the inline video info and inherit it in the full screen 14310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu int savePosition = 0; 14410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu boolean savedIsPlaying = false; 14510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null) { 14610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // If we are playing the same video, then it is better to 14710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // save the current position. 14810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (layerId == mHTML5VideoView.getVideoLayerId()) { 14910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu savePosition = mHTML5VideoView.getCurrentPosition(); 15010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu savedIsPlaying = mHTML5VideoView.isPlaying(); 15110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 15310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.release(); 15410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 15510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(), 15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu layerId, savePosition, savedIsPlaying); 15710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCurrentProxy = proxy; 15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 16010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 16110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView); 16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 16310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 164661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // This is on the UI thread. 165661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When native tell Java to play, we need to check whether or not it is 166661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // still the same video by using videoLayerId and treat it differently. 167290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void play(String url, int time, HTML5VideoViewProxy proxy, 168661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu WebChromeClient client, int videoLayerId) { 169661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = -1; 17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu boolean backFromFullScreenMode = false; 17110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null) { 172661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 17310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView instanceof HTML5VideoFullScreen) { 17410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu backFromFullScreenMode = true; 17510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 17610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 177661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 17810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (backFromFullScreenMode 17910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu || currentVideoLayerId != videoLayerId 180661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu || mHTML5VideoView.getSurfaceTexture() == null) { 181661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when switching to a new video, 182661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // either inside a WebView or across WebViews 183661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // For switching videos within a WebView or across the WebView, 184661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // we need to pause the old one and re-create a new media player 185661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // inside the HTML5VideoView. 186661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 187661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 188661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // release the media player to avoid finalize error 189661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.release(); 190a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu } 191661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy = proxy; 19210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, false); 193a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu 19410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.prepareDataAndDisplayMode(proxy); 196661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } else if (mCurrentProxy == proxy) { 197661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when we keep playing with one video 198661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (!mHTML5VideoView.isPlaying()) { 199661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 200661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.start(); 201661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 202661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } else if (mCurrentProxy != null) { 20310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Some other video is already playing. Notify the caller that 20410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // its playback ended. 205661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu proxy.dispatchOnEnded(); 206bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 20764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 208290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 209048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static boolean isPlaying(HTML5VideoViewProxy proxy) { 210661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu return (mCurrentProxy == proxy && mHTML5VideoView != null 211661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu && mHTML5VideoView.isPlaying()); 212048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 213048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 214048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static int getCurrentPosition() { 215048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu int currentPosMs = 0; 216661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 217661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentPosMs = mHTML5VideoView.getCurrentPosition(); 218048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 219048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu return currentPosMs; 220048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 221048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 222290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void seek(int time, HTML5VideoViewProxy proxy) { 223661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && time >= 0 && mHTML5VideoView != null) { 224661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 225290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 226290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 227290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 228290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void pause(HTML5VideoViewProxy proxy) { 229661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && mHTML5VideoView != null) { 230661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pause(); 231290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 232290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 233bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu 234bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu public static void onPrepared() { 235158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu // The VideoView will decide whether to really kick off to play. 236158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu mHTML5VideoView.start(); 237265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu if (mBaseLayer != 0) { 238265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu setBaseLayer(mBaseLayer); 239265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu } 240661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 241661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 242661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void end() { 243661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy != null) { 244661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (isVideoSelfEnded) 245661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnEnded(); 246661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu else 247661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnPaused(); 248661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 249661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu isVideoSelfEnded = false; 250bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 251290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 252290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 253290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // A bunch event listeners for our VideoView 254290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnPreparedListener 255290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onPrepared(MediaPlayer mp) { 256bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu VideoPlayer.onPrepared(); 257290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, PREPARED); 258290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = new HashMap<String, Object>(); 259290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("dur", new Integer(mp.getDuration())); 260290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("width", new Integer(mp.getVideoWidth())); 261290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("height", new Integer(mp.getVideoHeight())); 262290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu msg.obj = map; 263290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 264290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 265290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 266290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnCompletionListener; 267290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onCompletion(MediaPlayer mp) { 268c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // The video ended by itself, so we need to 269c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // send a message to the UI thread to dismiss 270c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // the video view and to return to the WebView. 27143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang // arg1 == 1 means the video ends by itself. 27243aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang sendMessage(obtainMessage(ENDED, 1, 0)); 273290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 274290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 27550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // MediaPlayer.OnErrorListener 27650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public boolean onError(MediaPlayer mp, int what, int extra) { 27750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(obtainMessage(ERROR)); 27850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu return false; 27950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 28050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu 281c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu public void dispatchOnEnded() { 282290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, ENDED); 283290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 28464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 2853c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 28643aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang public void dispatchOnPaused() { 28743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang Message msg = Message.obtain(mWebCoreHandler, PAUSED); 28843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang mWebCoreHandler.sendMessage(msg); 28943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang } 29043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang 291048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public void onTimeupdate() { 292048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendMessage(obtainMessage(TIMEUPDATE)); 293048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 294048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 295661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When there is a frame ready from surface texture, we should tell WebView 296661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // to refresh. 297661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu @Override 298661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void onFrameAvailable(SurfaceTexture surfaceTexture) { 299661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // TODO: This should support partial invalidation too. 300661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.invalidate(); 301661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 302661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 303048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Handler for the messages from WebCore or Timer thread to the UI thread. 30464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 30564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 30664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This executes on the UI thread. 30764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 30864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu case PLAY: { 30964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String url = (String) msg.obj; 31064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 311661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int videoLayerID = msg.arg1; 31264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (client != null) { 313661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.play(url, mSeekPosition, this, client, videoLayerID); 31464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 31564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu break; 31664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 317290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case SEEK: { 318290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer time = (Integer) msg.obj; 319290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mSeekPosition = time; 320290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.seek(mSeekPosition, this); 321290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 322290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 323290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PAUSE: { 324290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.pause(this); 325290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 326290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 32746a83b4ead517b9fc13b4bee4c59c3eaf4d3fdd9Andrei Popescu case ENDED: 32843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang if (msg.arg1 == 1) 32943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang VideoPlayer.isVideoSelfEnded = true; 330661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.end(); 331661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu break; 33250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case ERROR: { 33350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 33450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 33550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu client.onHideCustomView(); 33650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 33750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 33850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 33950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case LOAD_DEFAULT_POSTER: { 34050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 34150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 34250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu doSetPoster(client.getDefaultVideoPoster()); 34350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 34450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 34550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 346048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: { 347048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu if (VideoPlayer.isPlaying(this)) { 348048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendTimeupdate(); 349048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 350048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 351048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 352c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu case BUFFERING_START: { 353f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu VideoPlayer.setPlayerBuffering(true); 354c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu break; 355c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 356c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu case BUFFERING_END: { 357f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu VideoPlayer.setPlayerBuffering(false); 358c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu break; 359c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 36064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 36164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 36264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 36364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Everything below this comment executes on the WebCore thread, except for 36464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // the EventHandler methods, which are called on the network thread. 36564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 36664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class that knows how to download posters 36764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class PosterDownloader implements EventHandler { 36864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request queue. This is static as we have one queue for all posters. 36964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static RequestQueue mRequestQueue; 37064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static int mQueueRefCount = 0; 37164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster URL 37242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch private URL mUrl; 37364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy we're doing this for. 37464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private final HTML5VideoViewProxy mProxy; 37564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster bytes. We only touch this on the network thread. 37664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private ByteArrayOutputStream mPosterBytes; 37764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request handle. We only touch this on the WebCore thread. 37864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private RequestHandle mRequestHandle; 37964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response status code. 38064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private int mStatusCode; 38164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response headers. 38264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Headers mHeaders; 38364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler to handle messages on the WebCore thread. 38464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mHandler; 38564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 38664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public PosterDownloader(String url, HTML5VideoViewProxy proxy) { 38742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 38842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(url); 38942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 39042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 39142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 39264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mProxy = proxy; 39364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler = new Handler(); 39464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 39564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Start the download. Called on WebCore thread. 39664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void start() { 39764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu retainQueue(); 39842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 39942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if (mUrl == null) { 40042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch return; 40142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 40242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 40342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // Only support downloading posters over http/https. 40442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // FIXME: Add support for other schemes. WebKit seems able to load 40542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // posters over other schemes e.g. file://, but gets the dimensions wrong. 40642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch String protocol = mUrl.getProtocol(); 40742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if ("http".equals(protocol) || "https".equals(protocol)) { 40842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle = mRequestQueue.queueRequest(mUrl.toString(), "GET", null, 40942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch this, null, 0); 41042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 41164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 41264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel the download if active and release the queue. Called on WebCore thread. 41364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void cancelAndReleaseQueue() { 41464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 41564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle.cancel(); 41664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle = null; 41764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 41864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu releaseQueue(); 41964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 42064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // EventHandler methods. Executed on the network thread. 42164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void status(int major_version, 42264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int minor_version, 42364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int code, 42464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String reason_phrase) { 42564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mStatusCode = code; 42664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4273c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 42864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void headers(Headers headers) { 42964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHeaders = headers; 4303c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4313c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 43264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void data(byte[] data, int len) { 43364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes == null) { 43464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = new ByteArrayOutputStream(); 4353c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 43664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.write(data, 0, len); 4373c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4383c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 43964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void endData() { 44064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mStatusCode == 200) { 44164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes.size() > 0) { 44264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu Bitmap poster = BitmapFactory.decodeByteArray( 44364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.toByteArray(), 0, mPosterBytes.size()); 44450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mProxy.doSetPoster(poster); 44564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 44664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 44764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } else if (mStatusCode >= 300 && mStatusCode < 400) { 44864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // We have a redirect. 44942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 45042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(mHeaders.getLocation()); 45142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 45242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 45342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 45464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mUrl != null) { 45564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler.post(new Runnable() { 45664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void run() { 45764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 45842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle.setupRedirect(mUrl.toString(), mStatusCode, 45964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu new HashMap<String, String>()); 46064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 46164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 46264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }); 46364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 46464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4653c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4663c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 46764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void certificate(SslCertificate certificate) { 46864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. 4693c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4703c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 47164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void error(int id, String description) { 47264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 47364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 47464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 47564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public boolean handleSslErrorRequest(SslError error) { 47664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. If this happens, data() will never be called so 47764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // mPosterBytes will never be created, so no need to call cleanup. 47864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return false; 47964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 48064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Tears down the poster bytes stream. Called on network thread. 48164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void cleanup() { 48264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes != null) { 48364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu try { 48464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.close(); 48564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } catch (IOException ignored) { 48664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Ignored. 48764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } finally { 48864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = null; 48964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4903c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 49164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 49264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 49364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Queue management methods. Called on WebCore thread. 49464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void retainQueue() { 49564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestQueue == null) { 49664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = new RequestQueue(mProxy.getContext()); 4973c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 49864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mQueueRefCount++; 4993c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5003c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 50164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void releaseQueue() { 50264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mQueueRefCount == 0) { 50364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 50464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 50564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (--mQueueRefCount == 0) { 50664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue.shutdown(); 50764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = null; 50864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 5093c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5103c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5116fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 5126fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 5136fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Private constructor. 514290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param webView is the WebView that hosts the video. 515290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object. 5166fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 517290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private HTML5VideoViewProxy(WebView webView, int nativePtr) { 5186fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu // This handler is for the main (UI) thread. 5196fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu super(Looper.getMainLooper()); 5203c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // Save the WebView object. 5213c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu mWebView = webView; 522661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Pass Proxy into webview, such that every time we have a setBaseLayer 523661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // call, we tell this Proxy to call the native to update the layer tree 524661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // for the Video Layer's surface texture info 525661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.setHTML5VideoViewProxy(this); 526290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // Save the native ptr 527290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mNativePointer = nativePtr; 52864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // create the message handler for this thread 52964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu createWebCoreHandler(); 5306fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 5316fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 53264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void createWebCoreHandler() { 53364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mWebCoreHandler = new Handler() { 53464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 53564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 53664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 537290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PREPARED: { 538290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = (Map<String, Object>) msg.obj; 539290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer duration = (Integer) map.get("dur"); 540290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer width = (Integer) map.get("width"); 541290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer height = (Integer) map.get("height"); 542290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnPrepared(duration.intValue(), width.intValue(), 543290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu height.intValue(), mNativePointer); 544290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 545290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 546290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case ENDED: 547ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch mSeekPosition = 0; 548290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnEnded(mNativePointer); 549290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 55043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang case PAUSED: 55143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang nativeOnPaused(mNativePointer); 55243aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang break; 55350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case POSTER_FETCHED: 55450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Bitmap poster = (Bitmap) msg.obj; 55550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu nativeOnPosterFetched(poster, mNativePointer); 55650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 557048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: 558048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu nativeOnTimeupdate(msg.arg1, mNativePointer); 559048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 5603c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 56164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 56264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }; 56364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 56464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 56564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void doSetPoster(Bitmap poster) { 56664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (poster == null) { 56764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 5686fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 56950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // Save a ref to the bitmap and send it over to the WebCore thread. 57050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mPoster = poster; 57150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, POSTER_FETCHED); 57250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu msg.obj = poster; 57350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mWebCoreHandler.sendMessage(msg); 5746fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 5756fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 576048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private void sendTimeupdate() { 577048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, TIMEUPDATE); 578048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu msg.arg1 = VideoPlayer.getCurrentPosition(); 579048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu mWebCoreHandler.sendMessage(msg); 580048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 581048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 58264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public Context getContext() { 58364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return mWebView.getContext(); 58464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 58564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 58664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The public methods below are all called from WebKit only. 5876fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 5886fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Play a video stream. 5896fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param url is the URL of the video stream. 5906fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 591661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void play(String url, int position, int videoLayerID) { 59264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 59364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 59464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 595ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch 596ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch if (position > 0) { 597ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch seek(position); 598ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch } 5996fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu Message message = obtainMessage(PLAY); 600661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu message.arg1 = videoLayerID; 60164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu message.obj = url; 6026fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu sendMessage(message); 6036fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 6046fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 60564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 606290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Seek into the video stream. 607290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param time is the position in the video stream. 608290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 609290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void seek(int time) { 610290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(SEEK); 611290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu message.obj = new Integer(time); 612290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 613290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 614290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 615290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 616290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Pause the playback. 617290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 618290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void pause() { 619290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(PAUSE); 620290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 621290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 622290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 623290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 62450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu * Tear down this proxy object. 62564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 62650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public void teardown() { 62764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This is called by the C++ MediaPlayerPrivate dtor. 62864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 62964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 63064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 63164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 63250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mNativePointer = 0; 63364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 63464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 63564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 63664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * Load the poster image. 63764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * @param url is the URL of the poster image. 63864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 63964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void loadPoster(String url) { 64064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 64150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message message = obtainMessage(LOAD_DEFAULT_POSTER); 64250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(message); 64364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 64464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 64564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 64664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 64764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 64864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 64964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Load the poster asynchronously 65064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader = new PosterDownloader(url, this); 65164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.start(); 6520a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott } 6530a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott 65410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // These three function are called from UI thread only by WebView. 655661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void setBaseLayer(int layer) { 656661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.setBaseLayer(layer); 657661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 658661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 659661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void pauseAndDispatch() { 660661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.pauseAndDispatch(); 661661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 66210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 66310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void enterFullScreenVideo(int layerId, String url) { 66410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu VideoPlayer.enterFullScreenVideo(layerId, url, this, mWebView); 66510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 66610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 6676fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 6683c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * The factory for HTML5VideoViewProxy instances. 6696fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param webViewCore is the WebViewCore that is requesting the proxy. 6706fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * 6713c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * @return a new HTML5VideoViewProxy object. 6726fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 673290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static HTML5VideoViewProxy getInstance(WebViewCore webViewCore, int nativePtr) { 674290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr); 6756fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 676290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 6771708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch /* package */ WebView getWebView() { 6781708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch return mWebView; 6791708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch } 6801708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch 681290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnPrepared(int duration, int width, int height, int nativePointer); 682290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnEnded(int nativePointer); 68343aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang private native void nativeOnPaused(int nativePointer); 68450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private native void nativeOnPosterFetched(Bitmap poster, int nativePointer); 685048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private native void nativeOnTimeupdate(int position, int nativePointer); 686661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture, 687661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int baseLayer, int videoLayerId, int textureName, 688265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState); 689c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu 690c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu @Override 691c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu public boolean onInfo(MediaPlayer mp, int what, int extra) { 692c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) { 693c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu sendMessage(obtainMessage(BUFFERING_START, what, extra)); 694c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) { 695c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu sendMessage(obtainMessage(BUFFERING_END, what, extra)); 696c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 697c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu return false; 698c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 6996fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu} 700