HTML5VideoViewProxy.java revision 158fbdb29b8fdda57f942ec2056d908714c326be
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, 49661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu SurfaceTexture.OnFrameAvailableListener { 506fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu // Logging tag. 516fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu private static final String LOGTAG = "HTML5VideoViewProxy"; 526fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 533c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // Message Ids for WebCore thread -> UI thread communication. 5450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private static final int PLAY = 100; 5550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private static final int SEEK = 101; 5650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private static final int PAUSE = 102; 5750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private static final int ERROR = 103; 5850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private static final int LOAD_DEFAULT_POSTER = 104; 596fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 6064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Message Ids to be handled on the WebCore thread 61290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private static final int PREPARED = 200; 62290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private static final int ENDED = 201; 6350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private static final int POSTER_FETCHED = 202; 6443aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang private static final int PAUSED = 203; 6564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 66048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Timer thread -> UI thread 67048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private static final int TIMEUPDATE = 300; 68048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 69290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The C++ MediaPlayerPrivateAndroid object. 70290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu int mNativePointer; 7164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler for WebCore thread messages; 7264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mWebCoreHandler; 733c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // The WebView instance that created this view. 743c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu private WebView mWebView; 7564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster image to be shown when the video is not playing. 7650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // This ref prevents the bitmap from being GC'ed. 7750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private Bitmap mPoster; 7864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster downloader. 7964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private PosterDownloader mPosterDownloader; 80290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // The seek position. 81290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private int mSeekPosition; 8264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class to control the playback. This executes on the UI thread! 8364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class VideoPlayer { 8464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy that is currently playing (if any). 8564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static HTML5VideoViewProxy mCurrentProxy; 8664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The VideoView instance. This is a singleton for now, at least until 8764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // http://b/issue?id=1973663 is fixed. 88661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static HTML5VideoView mHTML5VideoView; 89048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 90661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static boolean isVideoSelfEnded = false; 91661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // By using the baseLayer and the current video Layer ID, we can 92661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // identify the exact layer on the UI thread to use the SurfaceTexture. 93661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private static int mBaseLayer = 0; 94661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 95661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Every time webView setBaseLayer, this will be called. 96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When we found the Video layer, then we set the Surface Texture to it. 97661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Otherwise, we may want to delete the Surface Texture to save memory. 98661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void setBaseLayer(int layer) { 9910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Don't do this for full screen mode. 10010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null 10110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu && !mHTML5VideoView.isFullScreenMode()) { 102661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mBaseLayer = layer; 103661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(); 104661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int textureName = mHTML5VideoView.getTextureName(); 105661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 106661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 107661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) { 108265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState = mHTML5VideoView.getCurrentState(); 109661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu boolean foundInTree = nativeSendSurfaceTexture(surfTexture, 110661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu layer, currentVideoLayerId, textureName, 111265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu playerState); 112265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu if (playerState == HTML5VideoView.STATE_PREPARED 113265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu && !foundInTree) { 114661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 115661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.deleteSurfaceTexture(); 11631d2aa1e17f1ee580edb762a6ef634098bba02bbAndrei Popescu } 11764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 119661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 120661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 121661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When a WebView is paused, we also want to pause the video in it. 122661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void pauseAndDispatch() { 123661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 124661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 125661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When switching out, clean the video content on the old page 126661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // by telling the layer not readyToUseSurfTex. 127661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu setBaseLayer(mBaseLayer); 128661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 129661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 13064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 13110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public static void enterFullScreenVideo(int layerId, String url, 13210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu HTML5VideoViewProxy proxy, WebView webView) { 13310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Save the inline video info and inherit it in the full screen 13410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu int savePosition = 0; 13510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu boolean savedIsPlaying = false; 13610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null) { 13710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // If we are playing the same video, then it is better to 13810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // save the current position. 13910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (layerId == mHTML5VideoView.getVideoLayerId()) { 14010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu savePosition = mHTML5VideoView.getCurrentPosition(); 14110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu savedIsPlaying = mHTML5VideoView.isPlaying(); 14210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 14310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 14410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.release(); 14510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 14610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(), 14710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu layerId, savePosition, savedIsPlaying); 14810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mCurrentProxy = proxy; 14910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 15010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 15110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView); 15310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 15410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 155661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // This is on the UI thread. 156661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When native tell Java to play, we need to check whether or not it is 157661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // still the same video by using videoLayerId and treat it differently. 158290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void play(String url, int time, HTML5VideoViewProxy proxy, 159661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu WebChromeClient client, int videoLayerId) { 160661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int currentVideoLayerId = -1; 16110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu boolean backFromFullScreenMode = false; 16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 16310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView != null) { 164661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); 16510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (mHTML5VideoView instanceof HTML5VideoFullScreen) { 16610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu backFromFullScreenMode = true; 16710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 16810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 169661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu if (backFromFullScreenMode 17110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu || currentVideoLayerId != videoLayerId 172661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu || mHTML5VideoView.getSurfaceTexture() == null) { 173661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when switching to a new video, 174661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // either inside a WebView or across WebViews 175661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // For switching videos within a WebView or across the WebView, 176661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // we need to pause the old one and re-create a new media player 177661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // inside the HTML5VideoView. 178661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 179661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pauseAndDispatch(mCurrentProxy); 180661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // release the media player to avoid finalize error 181661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.release(); 182a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu } 183661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy = proxy; 18410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, false); 185a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu 18610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.setVideoURI(url, mCurrentProxy); 18710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu mHTML5VideoView.prepareDataAndDisplayMode(proxy); 188661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } else if (mCurrentProxy == proxy) { 189661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Here, we handle the case when we keep playing with one video 190661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (!mHTML5VideoView.isPlaying()) { 191661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 192661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.start(); 193661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 194661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } else if (mCurrentProxy != null) { 19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // Some other video is already playing. Notify the caller that 19610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // its playback ended. 197661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu proxy.dispatchOnEnded(); 198bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 19964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 200290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 201048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static boolean isPlaying(HTML5VideoViewProxy proxy) { 202661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu return (mCurrentProxy == proxy && mHTML5VideoView != null 203661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu && mHTML5VideoView.isPlaying()); 204048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 205048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 206048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public static int getCurrentPosition() { 207048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu int currentPosMs = 0; 208661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mHTML5VideoView != null) { 209661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu currentPosMs = mHTML5VideoView.getCurrentPosition(); 210048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 211048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu return currentPosMs; 212048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 213048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 214290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void seek(int time, HTML5VideoViewProxy proxy) { 215661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && time >= 0 && mHTML5VideoView != null) { 216661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.seekTo(time); 217290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 218290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 219290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 220290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static void pause(HTML5VideoViewProxy proxy) { 221661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy == proxy && mHTML5VideoView != null) { 222661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mHTML5VideoView.pause(); 223290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 224290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 225bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu 226bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu public static void onPrepared() { 227158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu // The VideoView will decide whether to really kick off to play. 228158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu mHTML5VideoView.start(); 229265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu if (mBaseLayer != 0) { 230265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu setBaseLayer(mBaseLayer); 231265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu } 232661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 233661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 234661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public static void end() { 235661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (mCurrentProxy != null) { 236661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu if (isVideoSelfEnded) 237661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnEnded(); 238661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu else 239661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mCurrentProxy.dispatchOnPaused(); 240661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 241661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu isVideoSelfEnded = false; 242bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu } 243290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 244290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 245290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // A bunch event listeners for our VideoView 246290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnPreparedListener 247290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onPrepared(MediaPlayer mp) { 248bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu VideoPlayer.onPrepared(); 249290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, PREPARED); 250290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = new HashMap<String, Object>(); 251290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("dur", new Integer(mp.getDuration())); 252290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("width", new Integer(mp.getVideoWidth())); 253290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu map.put("height", new Integer(mp.getVideoHeight())); 254290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu msg.obj = map; 255290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 256290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 257290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 258290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // MediaPlayer.OnCompletionListener; 259290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void onCompletion(MediaPlayer mp) { 260c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // The video ended by itself, so we need to 261c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // send a message to the UI thread to dismiss 262c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu // the video view and to return to the WebView. 26343aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang // arg1 == 1 means the video ends by itself. 26443aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang sendMessage(obtainMessage(ENDED, 1, 0)); 265290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 266290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 26750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // MediaPlayer.OnErrorListener 26850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public boolean onError(MediaPlayer mp, int what, int extra) { 26950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(obtainMessage(ERROR)); 27050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu return false; 27150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 27250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu 273c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu public void dispatchOnEnded() { 274290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message msg = Message.obtain(mWebCoreHandler, ENDED); 275290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mWebCoreHandler.sendMessage(msg); 27664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 2773c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 27843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang public void dispatchOnPaused() { 27943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang Message msg = Message.obtain(mWebCoreHandler, PAUSED); 28043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang mWebCoreHandler.sendMessage(msg); 28143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang } 28243aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang 283048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu public void onTimeupdate() { 284048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendMessage(obtainMessage(TIMEUPDATE)); 285048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 286048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 287661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // When there is a frame ready from surface texture, we should tell WebView 288661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // to refresh. 289661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu @Override 290661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void onFrameAvailable(SurfaceTexture surfaceTexture) { 291661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // TODO: This should support partial invalidation too. 292661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.invalidate(); 293661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 294661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 295048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu // Handler for the messages from WebCore or Timer thread to the UI thread. 29664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 29764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 29864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This executes on the UI thread. 29964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 30064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu case PLAY: { 30164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String url = (String) msg.obj; 30264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 303661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int videoLayerID = msg.arg1; 30464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (client != null) { 305661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.play(url, mSeekPosition, this, client, videoLayerID); 30664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 30764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu break; 30864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 309290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case SEEK: { 310290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer time = (Integer) msg.obj; 311290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mSeekPosition = time; 312290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.seek(mSeekPosition, this); 313290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 314290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 315290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PAUSE: { 316290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu VideoPlayer.pause(this); 317290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 318290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 31946a83b4ead517b9fc13b4bee4c59c3eaf4d3fdd9Andrei Popescu case ENDED: 32043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang if (msg.arg1 == 1) 32143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang VideoPlayer.isVideoSelfEnded = true; 322661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.end(); 323661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu break; 32450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case ERROR: { 32550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 32650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 32750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu client.onHideCustomView(); 32850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 32950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 33050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 33150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case LOAD_DEFAULT_POSTER: { 33250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu WebChromeClient client = mWebView.getWebChromeClient(); 33350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu if (client != null) { 33450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu doSetPoster(client.getDefaultVideoPoster()); 33550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 33650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 33750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu } 338048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: { 339048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu if (VideoPlayer.isPlaying(this)) { 340048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu sendTimeupdate(); 341048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 342048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 343048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 34464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 34564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 34664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 34764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Everything below this comment executes on the WebCore thread, except for 34864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // the EventHandler methods, which are called on the network thread. 34964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 35064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // A helper class that knows how to download posters 35164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static final class PosterDownloader implements EventHandler { 35264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request queue. This is static as we have one queue for all posters. 35364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static RequestQueue mRequestQueue; 35464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private static int mQueueRefCount = 0; 35564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster URL 35642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch private URL mUrl; 35764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The proxy we're doing this for. 35864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private final HTML5VideoViewProxy mProxy; 35964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The poster bytes. We only touch this on the network thread. 36064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private ByteArrayOutputStream mPosterBytes; 36164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The request handle. We only touch this on the WebCore thread. 36264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private RequestHandle mRequestHandle; 36364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response status code. 36464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private int mStatusCode; 36564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The response headers. 36664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Headers mHeaders; 36764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The handler to handle messages on the WebCore thread. 36864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private Handler mHandler; 36964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 37064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public PosterDownloader(String url, HTML5VideoViewProxy proxy) { 37142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 37242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(url); 37342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 37442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 37542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 37664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mProxy = proxy; 37764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler = new Handler(); 37864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 37964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Start the download. Called on WebCore thread. 38064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void start() { 38164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu retainQueue(); 38242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 38342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if (mUrl == null) { 38442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch return; 38542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 38642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch 38742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // Only support downloading posters over http/https. 38842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // FIXME: Add support for other schemes. WebKit seems able to load 38942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch // posters over other schemes e.g. file://, but gets the dimensions wrong. 39042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch String protocol = mUrl.getProtocol(); 39142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch if ("http".equals(protocol) || "https".equals(protocol)) { 39242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle = mRequestQueue.queueRequest(mUrl.toString(), "GET", null, 39342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch this, null, 0); 39442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 39564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 39664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel the download if active and release the queue. Called on WebCore thread. 39764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void cancelAndReleaseQueue() { 39864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 39964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle.cancel(); 40064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestHandle = null; 40164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 40264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu releaseQueue(); 40364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 40464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // EventHandler methods. Executed on the network thread. 40564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void status(int major_version, 40664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int minor_version, 40764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu int code, 40864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu String reason_phrase) { 40964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mStatusCode = code; 41064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4113c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 41264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void headers(Headers headers) { 41364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHeaders = headers; 4143c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4153c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 41664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void data(byte[] data, int len) { 41764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes == null) { 41864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = new ByteArrayOutputStream(); 4193c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 42064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.write(data, 0, len); 4213c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4223c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 42364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void endData() { 42464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mStatusCode == 200) { 42564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes.size() > 0) { 42664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu Bitmap poster = BitmapFactory.decodeByteArray( 42764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.toByteArray(), 0, mPosterBytes.size()); 42850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mProxy.doSetPoster(poster); 42964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 43064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 43164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } else if (mStatusCode >= 300 && mStatusCode < 400) { 43264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // We have a redirect. 43342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch try { 43442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = new URL(mHeaders.getLocation()); 43542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } catch (MalformedURLException e) { 43642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mUrl = null; 43742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch } 43864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mUrl != null) { 43964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mHandler.post(new Runnable() { 44064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void run() { 44164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestHandle != null) { 44242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch mRequestHandle.setupRedirect(mUrl.toString(), mStatusCode, 44364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu new HashMap<String, String>()); 44464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 44564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 44664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }); 44764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 44864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4493c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4503c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 45164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void certificate(SslCertificate certificate) { 45264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. 4533c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4543c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 45564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void error(int id, String description) { 45664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu cleanup(); 45764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 45864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 45964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public boolean handleSslErrorRequest(SslError error) { 46064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Don't care. If this happens, data() will never be called so 46164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // mPosterBytes will never be created, so no need to call cleanup. 46264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return false; 46364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 46464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Tears down the poster bytes stream. Called on network thread. 46564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void cleanup() { 46664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterBytes != null) { 46764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu try { 46864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes.close(); 46964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } catch (IOException ignored) { 47064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Ignored. 47164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } finally { 47264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterBytes = null; 47364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4743c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 47564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 47664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 47764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Queue management methods. Called on WebCore thread. 47864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void retainQueue() { 47964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mRequestQueue == null) { 48064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = new RequestQueue(mProxy.getContext()); 4813c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 48264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mQueueRefCount++; 4833c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4843c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu 48564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void releaseQueue() { 48664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mQueueRefCount == 0) { 48764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 48864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 48964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (--mQueueRefCount == 0) { 49064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue.shutdown(); 49164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mRequestQueue = null; 49264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 4933c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4943c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 4956fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 4966fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 4976fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Private constructor. 498290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param webView is the WebView that hosts the video. 499290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object. 5006fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 501290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private HTML5VideoViewProxy(WebView webView, int nativePtr) { 5026fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu // This handler is for the main (UI) thread. 5036fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu super(Looper.getMainLooper()); 5043c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu // Save the WebView object. 5053c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu mWebView = webView; 506661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // Pass Proxy into webview, such that every time we have a setBaseLayer 507661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // call, we tell this Proxy to call the native to update the layer tree 508661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu // for the Video Layer's surface texture info 509661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu mWebView.setHTML5VideoViewProxy(this); 510290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu // Save the native ptr 511290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu mNativePointer = nativePtr; 51264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // create the message handler for this thread 51364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu createWebCoreHandler(); 5146fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 5156fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 51664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void createWebCoreHandler() { 51764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mWebCoreHandler = new Handler() { 51864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu @Override 51964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void handleMessage(Message msg) { 52064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu switch (msg.what) { 521290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case PREPARED: { 522290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Map<String, Object> map = (Map<String, Object>) msg.obj; 523290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer duration = (Integer) map.get("dur"); 524290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer width = (Integer) map.get("width"); 525290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Integer height = (Integer) map.get("height"); 526290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnPrepared(duration.intValue(), width.intValue(), 527290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu height.intValue(), mNativePointer); 528290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 529290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 530290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu case ENDED: 531ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch mSeekPosition = 0; 532290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu nativeOnEnded(mNativePointer); 533290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu break; 53443aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang case PAUSED: 53543aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang nativeOnPaused(mNativePointer); 53643aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang break; 53750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu case POSTER_FETCHED: 53850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Bitmap poster = (Bitmap) msg.obj; 53950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu nativeOnPosterFetched(poster, mNativePointer); 54050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu break; 541048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu case TIMEUPDATE: 542048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu nativeOnTimeupdate(msg.arg1, mNativePointer); 543048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu break; 5443c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu } 54564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 54664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu }; 54764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 54864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 54964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu private void doSetPoster(Bitmap poster) { 55064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (poster == null) { 55164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 5526fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 55350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu // Save a ref to the bitmap and send it over to the WebCore thread. 55450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mPoster = poster; 55550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, POSTER_FETCHED); 55650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu msg.obj = poster; 55750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mWebCoreHandler.sendMessage(msg); 5586fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 5596fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 560048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private void sendTimeupdate() { 561048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu Message msg = Message.obtain(mWebCoreHandler, TIMEUPDATE); 562048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu msg.arg1 = VideoPlayer.getCurrentPosition(); 563048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu mWebCoreHandler.sendMessage(msg); 564048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu } 565048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu 56664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public Context getContext() { 56764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return mWebView.getContext(); 56864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 56964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 57064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // The public methods below are all called from WebKit only. 5716fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 5726fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Play a video stream. 5736fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param url is the URL of the video stream. 5746fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 575661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void play(String url, int position, int videoLayerID) { 57664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 57764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 57864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 579ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch 580ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch if (position > 0) { 581ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch seek(position); 582ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch } 5836fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu Message message = obtainMessage(PLAY); 584661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu message.arg1 = videoLayerID; 58564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu message.obj = url; 5866fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu sendMessage(message); 5876fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 5886fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu 58964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 590290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Seek into the video stream. 591290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * @param time is the position in the video stream. 592290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 593290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void seek(int time) { 594290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(SEEK); 595290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu message.obj = new Integer(time); 596290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 597290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 598290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 599290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 600290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu * Pause the playback. 601290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu */ 602290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public void pause() { 603290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu Message message = obtainMessage(PAUSE); 604290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu sendMessage(message); 605290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu } 606290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 607290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu /** 60850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu * Tear down this proxy object. 60964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 61050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu public void teardown() { 61164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // This is called by the C++ MediaPlayerPrivate dtor. 61264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 61364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 61464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 61564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 61650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu mNativePointer = 0; 61764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 61864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu 61964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu /** 62064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * Load the poster image. 62164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu * @param url is the URL of the poster image. 62264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu */ 62364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu public void loadPoster(String url) { 62464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (url == null) { 62550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu Message message = obtainMessage(LOAD_DEFAULT_POSTER); 62650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu sendMessage(message); 62764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu return; 62864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 62964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Cancel any active poster download. 63064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu if (mPosterDownloader != null) { 63164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.cancelAndReleaseQueue(); 63264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu } 63364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu // Load the poster asynchronously 63464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader = new PosterDownloader(url, this); 63564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu mPosterDownloader.start(); 6360a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott } 6370a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott 63810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu // These three function are called from UI thread only by WebView. 639661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void setBaseLayer(int layer) { 640661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.setBaseLayer(layer); 641661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 642661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu 643661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu public void pauseAndDispatch() { 644661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu VideoPlayer.pauseAndDispatch(); 645661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu } 64610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 64710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu public void enterFullScreenVideo(int layerId, String url) { 64810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu VideoPlayer.enterFullScreenVideo(layerId, url, this, mWebView); 64910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu } 65010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu 6516fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu /** 6523c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * The factory for HTML5VideoViewProxy instances. 6536fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * @param webViewCore is the WebViewCore that is requesting the proxy. 6546fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * 6553c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * @return a new HTML5VideoViewProxy object. 6566fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */ 657290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu public static HTML5VideoViewProxy getInstance(WebViewCore webViewCore, int nativePtr) { 658290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr); 6596fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu } 660290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu 6611708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch /* package */ WebView getWebView() { 6621708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch return mWebView; 6631708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch } 6641708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch 665290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnPrepared(int duration, int width, int height, int nativePointer); 666290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu private native void nativeOnEnded(int nativePointer); 66743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang private native void nativeOnPaused(int nativePointer); 66850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu private native void nativeOnPosterFetched(Bitmap poster, int nativePointer); 669048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu private native void nativeOnTimeupdate(int position, int nativePointer); 670661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture, 671661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu int baseLayer, int videoLayerId, int textureName, 672265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu int playerState); 6736fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu} 674