HTML5VideoViewProxy.java revision c3a2858de909145a382e7932d5fb044e1388c0b3
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; 62c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu private static final int ENTER_FULLSCREEN = 107; 636fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 6464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Message Ids to be handled on the WebCore thread 65290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private static final int PREPARED = 200; 66290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private static final int ENDED = 201; 6750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private static final int POSTER_FETCHED = 202; 6843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang private static final int PAUSED = 203; 69b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu private static final int STOPFULLSCREEN = 204; 70e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu private static final int RESTORESTATE = 205; 7164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 72048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Timer thread -> UI thread 73048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private static final int TIMEUPDATE = 300; 74048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 75290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The C++ MediaPlayerPrivateAndroid object. 76290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu int mNativePointer; 7764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler for WebCore thread messages; 7864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mWebCoreHandler; 793c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon // The WebViewClassic instance that created this view. 803c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon private WebViewClassic mWebView; 8164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster image to be shown when the video is not playing. 8250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // This ref prevents the bitmap from being GC'ed. 8350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private Bitmap mPoster; 8464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster downloader. 8564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private PosterDownloader mPosterDownloader; 86290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The seek position. 87290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private int mSeekPosition; 8864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class to control the playback. This executes on the UI thread! 8964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class VideoPlayer { 9064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy that is currently playing (if any). 9164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static HTML5VideoViewProxy mCurrentProxy; 9264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The VideoView instance. This is a singleton for now, at least until 9364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // http://b/issue?id=1973663 is fixed. 94661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static HTML5VideoView mHTML5VideoView; 95048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static boolean isVideoSelfEnded = false; 97661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // By using the baseLayer and the current video Layer ID, we can 98661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // identify the exact layer on the UI thread to use the SurfaceTexture. 99661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static int mBaseLayer = 0; 100661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 101f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu private static void setPlayerBuffering(boolean playerBuffering) { 102f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu mHTML5VideoView.setPlayerBuffering(playerBuffering); 103f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu } 104f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu 105661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Every time webView setBaseLayer, this will be called. 106661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When we found the Video layer, then we set the Surface Texture to it. 107661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Otherwise, we may want to delete the Surface Texture to save memory. 108661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void setBaseLayer(int layer) { 109c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mBaseLayer = layer; 11010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Don't do this for full screen mode. 11110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null 112c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu && !mHTML5VideoView.isFullScreenMode()) { 113661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 114c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu SurfaceTexture surfTexture = 115c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu HTML5VideoInline.getSurfaceTexture(currentVideoLayerId); 1163fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu int textureName = mHTML5VideoView.getTextureName(); 1173fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu 118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) { 119265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState = mHTML5VideoView.getCurrentState(); 120f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu if (mHTML5VideoView.getPlayerBuffering()) 121c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu playerState = HTML5VideoView.STATE_PREPARING; 122661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu boolean foundInTree = nativeSendSurfaceTexture(surfTexture, 123661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu layer, currentVideoLayerId, textureName, 124265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu playerState); 1251e26d82ffaf983dc288152cfe8c0a821de33f2a4Teng-Hui Zhu if (playerState >= HTML5VideoView.STATE_PREPARED 126265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu && !foundInTree) { 127661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 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 } 138661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 13964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 14010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public static void enterFullScreenVideo(int layerId, String url, 1413c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon HTML5VideoViewProxy proxy, WebViewClassic webView) { 14210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Save the inline video info and inherit it in the full screen 14310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu int savePosition = 0; 144c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu boolean canSkipPrepare = false; 1456a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu boolean forceStart = false; 14610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null) { 1472b64c5a6f70bfae7db95f763441b52a506d6f630Teng-Hui Zhu // We don't allow enter full screen mode while the previous 1482b64c5a6f70bfae7db95f763441b52a506d6f630Teng-Hui Zhu // full screen video hasn't finished yet. 1492b64c5a6f70bfae7db95f763441b52a506d6f630Teng-Hui Zhu if (!mHTML5VideoView.fullScreenExited() && mHTML5VideoView.isFullScreenMode()) { 1502b64c5a6f70bfae7db95f763441b52a506d6f630Teng-Hui Zhu Log.w(LOGTAG, "Try to reenter the full screen mode"); 1512b64c5a6f70bfae7db95f763441b52a506d6f630Teng-Hui Zhu return; 1522b64c5a6f70bfae7db95f763441b52a506d6f630Teng-Hui Zhu } 1536a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu int playerState = mHTML5VideoView.getCurrentState(); 15410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // If we are playing the same video, then it is better to 15510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // save the current position. 15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (layerId == mHTML5VideoView.getVideoLayerId()) { 15710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu savePosition = mHTML5VideoView.getCurrentPosition(); 158c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu canSkipPrepare = (playerState == HTML5VideoView.STATE_PREPARING 159c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu || playerState == HTML5VideoView.STATE_PREPARED 160c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu || playerState == HTML5VideoView.STATE_PLAYING) 161c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu && !mHTML5VideoView.isFullScreenMode(); 162c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu } 163c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu if (!canSkipPrepare) { 164c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mHTML5VideoView.reset(); 1656a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu } else { 1666a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu forceStart = playerState == HTML5VideoView.STATE_PREPARING 1676a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu || playerState == HTML5VideoView.STATE_PLAYING; 16810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 16910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(), 171c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu layerId, savePosition, canSkipPrepare); 1726a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu mHTML5VideoView.setStartWhenPrepared(forceStart); 17310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCurrentProxy = proxy; 17410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 17510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView); 17610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 17710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 178d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu public static void exitFullScreenVideo(HTML5VideoViewProxy proxy, 1793c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon WebViewClassic webView) { 180d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu if (!mHTML5VideoView.fullScreenExited() && mHTML5VideoView.isFullScreenMode()) { 181d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu WebChromeClient client = webView.getWebChromeClient(); 182d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu if (client != null) { 183d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu client.onHideCustomView(); 184d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 185d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 186d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 187d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu 188661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // This is on the UI thread. 189661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When native tell Java to play, we need to check whether or not it is 190661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // still the same video by using videoLayerId and treat it differently. 191290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void play(String url, int time, HTML5VideoViewProxy proxy, 192661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu WebChromeClient client, int videoLayerId) { 193661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = -1; 19410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu boolean backFromFullScreenMode = false; 19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null) { 196661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 1971a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu backFromFullScreenMode = mHTML5VideoView.fullScreenExited(); 19896fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu 19996fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // When playing video back to back in full screen mode, 20096fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // javascript will switch the src and call play. 20196fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // In this case, we can just reuse the same full screen view, 20296fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu // and play the video after prepared. 20396fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu if (mHTML5VideoView.isFullScreenMode() 20496fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu && !backFromFullScreenMode 20596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu && currentVideoLayerId != videoLayerId 20696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu && mCurrentProxy != proxy) { 20796fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mCurrentProxy = proxy; 20896fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mHTML5VideoView.setStartWhenPrepared(true); 20996fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mHTML5VideoView.setVideoURI(url, proxy); 21096fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu mHTML5VideoView.reprepareData(proxy); 21196fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu return; 21296fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu } 21310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 214661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 215c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu boolean skipPrepare = false; 216c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu boolean createInlineView = false; 217c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu if (backFromFullScreenMode && currentVideoLayerId == videoLayerId) { 218c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu skipPrepare = true; 219c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu createInlineView = true; 220c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } else if(backFromFullScreenMode 2213fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu || currentVideoLayerId != videoLayerId 222c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu || HTML5VideoInline.surfaceTextureDeleted()) { 223661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when switching to a new video, 224661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // either inside a WebView or across WebViews 225661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // For switching videos within a WebView or across the WebView, 226661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // we need to pause the old one and re-create a new media player 227661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // inside the HTML5VideoView. 228661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 22922954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu if (!backFromFullScreenMode) { 23022954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 23122954d435d645d48885f653bd4ca6bc79e1bcd83Teng-Hui Zhu } 232c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu mHTML5VideoView.reset(); 233a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu } 234c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu createInlineView = true; 235c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } 236c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu if (createInlineView) { 237661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy = proxy; 238c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, skipPrepare); 239a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu 24010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 24110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.prepareDataAndDisplayMode(proxy); 242c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu return; 243c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } 244c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu 245c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu if (mCurrentProxy == proxy) { 246661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when we keep playing with one video 247661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (!mHTML5VideoView.isPlaying()) { 248661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 249661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.start(); 250661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 251661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } else if (mCurrentProxy != null) { 25210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Some other video is already playing. Notify the caller that 25310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // its playback ended. 254661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu proxy.dispatchOnEnded(); 255bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 25664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 257290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 258048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static boolean isPlaying(HTML5VideoViewProxy proxy) { 259661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu return (mCurrentProxy == proxy && mHTML5VideoView != null 260661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu && mHTML5VideoView.isPlaying()); 261048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 262048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 263048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static int getCurrentPosition() { 264048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu int currentPosMs = 0; 265661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 266661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentPosMs = mHTML5VideoView.getCurrentPosition(); 267048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 268048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu return currentPosMs; 269048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 270048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 271290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void seek(int time, HTML5VideoViewProxy proxy) { 272661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && time >= 0 && mHTML5VideoView != null) { 273661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 274290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 275290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 276290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 277290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void pause(HTML5VideoViewProxy proxy) { 278661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && mHTML5VideoView != null) { 279661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pause(); 280290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 281290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 282bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu 283bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu public static void onPrepared() { 284e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu if (!mHTML5VideoView.isFullScreenMode()) { 2850504967cb05f7bbd0c17962360a5d88ace8d173fTeng-Hui Zhu mHTML5VideoView.start(); 2860504967cb05f7bbd0c17962360a5d88ace8d173fTeng-Hui Zhu } 287661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 288661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 289661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void end() { 2904dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu mHTML5VideoView.showControllerInFullScreen(); 291661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy != null) { 292661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (isVideoSelfEnded) 293661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnEnded(); 294661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu else 295661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnPaused(); 296661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 297661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu isVideoSelfEnded = false; 298bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 299290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 300290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 301290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // A bunch event listeners for our VideoView 302290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnPreparedListener 303290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onPrepared(MediaPlayer mp) { 304bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu VideoPlayer.onPrepared(); 305290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, PREPARED); 306290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = new HashMap<String, Object>(); 307290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("dur", new Integer(mp.getDuration())); 308290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("width", new Integer(mp.getVideoWidth())); 309290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("height", new Integer(mp.getVideoHeight())); 310290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu msg.obj = map; 311290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 312290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 313290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 314290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnCompletionListener; 315290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onCompletion(MediaPlayer mp) { 316c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // The video ended by itself, so we need to 317c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // send a message to the UI thread to dismiss 318c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // the video view and to return to the WebView. 31943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang // arg1 == 1 means the video ends by itself. 32043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang sendMessage(obtainMessage(ENDED, 1, 0)); 321290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 322290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 32350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // MediaPlayer.OnErrorListener 32450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public boolean onError(MediaPlayer mp, int what, int extra) { 32550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(obtainMessage(ERROR)); 32650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu return false; 32750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 32850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu 329c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu public void dispatchOnEnded() { 330290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, ENDED); 331290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 33264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 3333c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 33443aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang public void dispatchOnPaused() { 335b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu Message msg = Message.obtain(mWebCoreHandler, PAUSED); 336b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu mWebCoreHandler.sendMessage(msg); 337b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu } 338b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu 339c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu public void dispatchOnStopFullScreen(boolean stillPlaying) { 340b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu Message msg = Message.obtain(mWebCoreHandler, STOPFULLSCREEN); 341c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu msg.arg1 = stillPlaying ? 1 : 0; 342b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu mWebCoreHandler.sendMessage(msg); 34343aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang } 34443aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang 345e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu public void dispatchOnRestoreState() { 346e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu Message msg = Message.obtain(mWebCoreHandler, RESTORESTATE); 347e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu mWebCoreHandler.sendMessage(msg); 348e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu } 349e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu 350048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public void onTimeupdate() { 351048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendMessage(obtainMessage(TIMEUPDATE)); 352048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 353048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 354661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When there is a frame ready from surface texture, we should tell WebView 355661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // to refresh. 356661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu @Override 357661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void onFrameAvailable(SurfaceTexture surfaceTexture) { 358661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // TODO: This should support partial invalidation too. 359661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.invalidate(); 360661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 361661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 362048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Handler for the messages from WebCore or Timer thread to the UI thread. 36364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 36464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 36564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This executes on the UI thread. 36664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 36764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu case PLAY: { 36864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String url = (String) msg.obj; 36964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 370661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int videoLayerID = msg.arg1; 37164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (client != null) { 372661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.play(url, mSeekPosition, this, client, videoLayerID); 37364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 37464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu break; 37564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 376c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu case ENTER_FULLSCREEN:{ 377c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu String url = (String) msg.obj; 378c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu WebChromeClient client = mWebView.getWebChromeClient(); 379c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu int videoLayerID = msg.arg1; 380c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu if (client != null) { 381c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu VideoPlayer.enterFullScreenVideo(videoLayerID, url, this, mWebView); 382c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } 383c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu break; 384c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } 385290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case SEEK: { 386290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer time = (Integer) msg.obj; 387290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mSeekPosition = time; 388290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.seek(mSeekPosition, this); 389290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 390290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 391290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PAUSE: { 392290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.pause(this); 393290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 394290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 39546a83b4ead517b9fc13b4bee4c59c3eaf4d3fdd9Andrei Popescu case ENDED: 39643aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang if (msg.arg1 == 1) 39743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang VideoPlayer.isVideoSelfEnded = true; 398661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.end(); 399661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu break; 40050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case ERROR: { 40150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 40250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 40350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu client.onHideCustomView(); 40450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 40550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 40650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 40750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case LOAD_DEFAULT_POSTER: { 40850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 40950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 41050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu doSetPoster(client.getDefaultVideoPoster()); 41150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 41250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 41350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 414048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: { 415048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu if (VideoPlayer.isPlaying(this)) { 416048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendTimeupdate(); 417048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 418048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 419048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 420c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu case BUFFERING_START: { 421f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu VideoPlayer.setPlayerBuffering(true); 422c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu break; 423c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 424c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu case BUFFERING_END: { 425f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu VideoPlayer.setPlayerBuffering(false); 426c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu break; 427c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 42864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 42964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 43064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 43164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Everything below this comment executes on the WebCore thread, except for 43264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // the EventHandler methods, which are called on the network thread. 43364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 43464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class that knows how to download posters 43564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class PosterDownloader implements EventHandler { 43664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request queue. This is static as we have one queue for all posters. 43764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static RequestQueue mRequestQueue; 43864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static int mQueueRefCount = 0; 43964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster URL 44042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch private URL mUrl; 44164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy we're doing this for. 44264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private final HTML5VideoViewProxy mProxy; 44364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster bytes. We only touch this on the network thread. 44464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private ByteArrayOutputStream mPosterBytes; 44564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request handle. We only touch this on the WebCore thread. 44664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private RequestHandle mRequestHandle; 44764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response status code. 44864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private int mStatusCode; 44964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response headers. 45064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Headers mHeaders; 45164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler to handle messages on the WebCore thread. 45264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mHandler; 45364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 45464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public PosterDownloader(String url, HTML5VideoViewProxy proxy) { 45542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 45642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(url); 45742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 45842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 45942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 46064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mProxy = proxy; 46164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler = new Handler(); 46264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 46364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Start the download. Called on WebCore thread. 46464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void start() { 46564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu retainQueue(); 46642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 46742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if (mUrl == null) { 46842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch return; 46942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 47042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 47142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // Only support downloading posters over http/https. 47242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // FIXME: Add support for other schemes. WebKit seems able to load 47342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // posters over other schemes e.g. file://, but gets the dimensions wrong. 47442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch String protocol = mUrl.getProtocol(); 47542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if ("http".equals(protocol) || "https".equals(protocol)) { 47642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle = mRequestQueue.queueRequest(mUrl.toString(), "GET", null, 47742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch this, null, 0); 47842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 47964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 48064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel the download if active and release the queue. Called on WebCore thread. 48164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void cancelAndReleaseQueue() { 48264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 48364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle.cancel(); 48464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle = null; 48564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 48664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu releaseQueue(); 48764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 48864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // EventHandler methods. Executed on the network thread. 48964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void status(int major_version, 49064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int minor_version, 49164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int code, 49264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String reason_phrase) { 49364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mStatusCode = code; 49464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4953c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 49664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void headers(Headers headers) { 49764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHeaders = headers; 4983c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4993c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 50064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void data(byte[] data, int len) { 50164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes == null) { 50264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = new ByteArrayOutputStream(); 5033c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 50464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.write(data, 0, len); 5053c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5063c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 50764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void endData() { 50864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mStatusCode == 200) { 50964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes.size() > 0) { 51064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu Bitmap poster = BitmapFactory.decodeByteArray( 51164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.toByteArray(), 0, mPosterBytes.size()); 51250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mProxy.doSetPoster(poster); 51364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 51464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 51564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } else if (mStatusCode >= 300 && mStatusCode < 400) { 51664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // We have a redirect. 51742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 51842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(mHeaders.getLocation()); 51942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 52042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 52142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 52264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mUrl != null) { 52364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler.post(new Runnable() { 52464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void run() { 52564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 52642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle.setupRedirect(mUrl.toString(), mStatusCode, 52764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu new HashMap<String, String>()); 52864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 52964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 53064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }); 53164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 53264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 5333c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5343c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 53564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void certificate(SslCertificate certificate) { 53664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. 5373c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5383c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 53964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void error(int id, String description) { 54064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 54164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 54264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 54364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public boolean handleSslErrorRequest(SslError error) { 54464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. If this happens, data() will never be called so 54564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // mPosterBytes will never be created, so no need to call cleanup. 54664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return false; 54764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 54864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Tears down the poster bytes stream. Called on network thread. 54964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void cleanup() { 55064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes != null) { 55164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu try { 55264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.close(); 55364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } catch (IOException ignored) { 55464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Ignored. 55564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } finally { 55664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = null; 55764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 5583c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 55964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 56064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 56164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Queue management methods. Called on WebCore thread. 56264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void retainQueue() { 56364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestQueue == null) { 56464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = new RequestQueue(mProxy.getContext()); 5653c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 56664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mQueueRefCount++; 5673c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5683c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 56964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void releaseQueue() { 57064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mQueueRefCount == 0) { 57164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 57264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 57364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (--mQueueRefCount == 0) { 57464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue.shutdown(); 57564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = null; 57664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 5773c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5783c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 5796fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 5806fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 5816fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Private constructor. 582290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param webView is the WebView that hosts the video. 583290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object. 5846fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 5853c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon private HTML5VideoViewProxy(WebViewClassic webView, int nativePtr) { 5866fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu // This handler is for the main (UI) thread. 5876fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu super(Looper.getMainLooper()); 5883c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // Save the WebView object. 5893c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu mWebView = webView; 590661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Pass Proxy into webview, such that every time we have a setBaseLayer 591661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // call, we tell this Proxy to call the native to update the layer tree 592661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // for the Video Layer's surface texture info 593661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.setHTML5VideoViewProxy(this); 594290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // Save the native ptr 595290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mNativePointer = nativePtr; 59664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // create the message handler for this thread 59764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu createWebCoreHandler(); 5986fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 5996fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 60064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void createWebCoreHandler() { 60164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mWebCoreHandler = new Handler() { 60264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 60364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 60464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 605290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PREPARED: { 606290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = (Map<String, Object>) msg.obj; 607290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer duration = (Integer) map.get("dur"); 608290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer width = (Integer) map.get("width"); 609290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer height = (Integer) map.get("height"); 610290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnPrepared(duration.intValue(), width.intValue(), 611290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu height.intValue(), mNativePointer); 612290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 613290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 614290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case ENDED: 615ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch mSeekPosition = 0; 616290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnEnded(mNativePointer); 617290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 61843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang case PAUSED: 61943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang nativeOnPaused(mNativePointer); 62043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang break; 62150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case POSTER_FETCHED: 62250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Bitmap poster = (Bitmap) msg.obj; 62350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu nativeOnPosterFetched(poster, mNativePointer); 62450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 625048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: 626048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu nativeOnTimeupdate(msg.arg1, mNativePointer); 627048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 628b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu case STOPFULLSCREEN: 629c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu nativeOnStopFullscreen(msg.arg1, mNativePointer); 630b109c8877139077fe25fa26ea2e0961b7cbb8341Teng-Hui Zhu break; 631e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu case RESTORESTATE: 632e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu nativeOnRestoreState(mNativePointer); 633e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu break; 6343c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 63564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 63664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }; 63764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 63864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 63964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void doSetPoster(Bitmap poster) { 64064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (poster == null) { 64164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 6426fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 64350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // Save a ref to the bitmap and send it over to the WebCore thread. 64450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mPoster = poster; 64550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, POSTER_FETCHED); 64650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu msg.obj = poster; 64750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mWebCoreHandler.sendMessage(msg); 6486fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 6496fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 650048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private void sendTimeupdate() { 651048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, TIMEUPDATE); 652048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu msg.arg1 = VideoPlayer.getCurrentPosition(); 653048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu mWebCoreHandler.sendMessage(msg); 654048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 655048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 65664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public Context getContext() { 65764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return mWebView.getContext(); 65864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 65964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 66064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The public methods below are all called from WebKit only. 6616fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 6626fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Play a video stream. 6636fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param url is the URL of the video stream. 6646fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 665661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void play(String url, int position, int videoLayerID) { 66664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 66764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 66864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 669ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch 670ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch if (position > 0) { 671ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch seek(position); 672ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch } 6736fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu Message message = obtainMessage(PLAY); 674661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu message.arg1 = videoLayerID; 67564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu message.obj = url; 6766fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu sendMessage(message); 6776fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 6786fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 67964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 680c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu * Play a video stream in full screen mode. 681c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu * @param url is the URL of the video stream. 682c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu */ 683c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu public void enterFullscreenForVideoLayer(String url, int videoLayerID) { 684c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu if (url == null) { 685c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu return; 686c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } 687c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu 688c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu Message message = obtainMessage(ENTER_FULLSCREEN); 689c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu message.arg1 = videoLayerID; 690c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu message.obj = url; 691c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu sendMessage(message); 692c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu } 693c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu 694c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu /** 695290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Seek into the video stream. 696290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param time is the position in the video stream. 697290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 698290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void seek(int time) { 699290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(SEEK); 700290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu message.obj = new Integer(time); 701290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 702290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 703290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 704290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 705290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Pause the playback. 706290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 707290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void pause() { 708290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(PAUSE); 709290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 710290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 711290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 712290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 71350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu * Tear down this proxy object. 71464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 71550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public void teardown() { 71664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This is called by the C++ MediaPlayerPrivate dtor. 71764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 71864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 71964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 72064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 72150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mNativePointer = 0; 72264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 72364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 72464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 72564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * Load the poster image. 72664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * @param url is the URL of the poster image. 72764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 72864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void loadPoster(String url) { 72964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 73050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message message = obtainMessage(LOAD_DEFAULT_POSTER); 73150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(message); 73264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 73364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 73464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 73564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 73664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 73764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 73864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Load the poster asynchronously 73964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader = new PosterDownloader(url, this); 74064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.start(); 7410a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott } 7420a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott 74310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // These three function are called from UI thread only by WebView. 744661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void setBaseLayer(int layer) { 745661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.setBaseLayer(layer); 746661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 747661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 748661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void pauseAndDispatch() { 749661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.pauseAndDispatch(); 750661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 75110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 75210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void enterFullScreenVideo(int layerId, String url) { 75310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu VideoPlayer.enterFullScreenVideo(layerId, url, this, mWebView); 75410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 75510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 756d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu public void exitFullScreenVideo() { 757d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu VideoPlayer.exitFullScreenVideo(this, mWebView); 758d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu } 759d7678a1684966cac10717b34b161b5241b9865c5Teng-Hui Zhu 7606fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 7613c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * The factory for HTML5VideoViewProxy instances. 7626fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param webViewCore is the WebViewCore that is requesting the proxy. 7636fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * 7643c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * @return a new HTML5VideoViewProxy object. 7656fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 766290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static HTML5VideoViewProxy getInstance(WebViewCore webViewCore, int nativePtr) { 767a6c4d8e018e39ff94263ce8f2a31b768104d1bb6Jonathan Dixon return new HTML5VideoViewProxy(webViewCore.getWebViewClassic(), nativePtr); 7686fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 769290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 7703c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon /* package */ WebViewClassic getWebView() { 7711708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch return mWebView; 7721708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch } 7731708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch 774290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnPrepared(int duration, int width, int height, int nativePointer); 775290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnEnded(int nativePointer); 77643aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang private native void nativeOnPaused(int nativePointer); 77750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private native void nativeOnPosterFetched(Bitmap poster, int nativePointer); 778048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private native void nativeOnTimeupdate(int position, int nativePointer); 779c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu private native void nativeOnStopFullscreen(int stillPlaying, int nativePointer); 780e4c89e321c7a33a7baf1a90237d21220d637e966Teng-Hui Zhu private native void nativeOnRestoreState(int nativePointer); 781661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture, 782661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int baseLayer, int videoLayerId, int textureName, 783265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState); 784c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu 785c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu @Override 786c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu public boolean onInfo(MediaPlayer mp, int what, int extra) { 787c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) { 788c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu sendMessage(obtainMessage(BUFFERING_START, what, extra)); 789c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) { 790c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu sendMessage(obtainMessage(BUFFERING_END, what, extra)); 791c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 792c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu return false; 793c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu } 7946fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu} 795