diff options
| author | Teng-Hui Zhu <ztenghui@google.com> | 2011-03-16 23:01:02 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-03-16 23:01:03 -0700 |
| commit | 7af7e00b9112f15d1683ae93975a6fcd9dd34da8 (patch) | |
| tree | 7634f4c3b91b8f4c979f2f6dd824998f533acc63 /core/java/android/webkit/HTML5VideoView.java | |
| parent | 8e42d39f0b1c2a60ab9c2f88cd3835ef8ae690ed (diff) | |
| parent | 10ab654943b386c0816a33dbd639c3b8d6260b01 (diff) | |
Merge "Support html5 video switching b/t full screen and inline mode" into honeycomb-mr1
Diffstat (limited to 'core/java/android/webkit/HTML5VideoView.java')
| -rw-r--r-- | core/java/android/webkit/HTML5VideoView.java | 226 |
1 files changed, 143 insertions, 83 deletions
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java index 2312160f5c66..ade7106fb093 100644 --- a/core/java/android/webkit/HTML5VideoView.java +++ b/core/java/android/webkit/HTML5VideoView.java @@ -4,72 +4,93 @@ package android.webkit; import android.graphics.SurfaceTexture; import android.media.MediaPlayer; import android.util.Log; +import android.view.SurfaceView; import android.webkit.HTML5VideoViewProxy; -import android.widget.MediaController; -import android.opengl.GLES20; import java.io.IOException; +import java.util.HashMap; import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; /** * @hide This is only used by the browser */ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{ - // Due to the fact that SurfaceTexture consume a lot of memory, we make it - // as static. m_textureNames is the texture bound with this SurfaceTexture. - private static SurfaceTexture mSurfaceTexture = null; - private static int[] mTextureNames; - // Only when the video is prepared, we render using SurfaceTexture. - // This in fact is used to avoid showing the obsolete content when - // switching videos. - private static boolean mReadyToUseSurfTex = false; + protected static final String LOGTAG = "HTML5VideoView"; + + protected static final String COOKIE = "Cookie"; + protected static final String HIDE_URL_LOGS = "x-hide-urls-from-log"; // For handling the seekTo before prepared, we need to know whether or not // the video is prepared. Therefore, we differentiate the state between // prepared and not prepared. // When the video is not prepared, we will have to save the seekTo time, // and use it when prepared to play. - private static final int STATE_NOTPREPARED = 0; - private static final int STATE_PREPARED = 1; + protected static final int STATE_NOTPREPARED = 0; + protected static final int STATE_PREPARED = 1; - // We only need state for handling seekTo - private int mCurrentState; + protected int mCurrentState; - // Basically for calling back the OnPrepared in the proxy - private HTML5VideoViewProxy mProxy; + protected HTML5VideoViewProxy mProxy; // Save the seek time when not prepared. This can happen when switching // video besides initial load. - private int mSaveSeekTime; + protected int mSaveSeekTime; // This is used to find the VideoLayer on the native side. - private int mVideoLayerId; + protected int mVideoLayerId; // Every video will have one MediaPlayer. Given the fact we only have one // SurfaceTexture, there is only one MediaPlayer in action. Every time we // switch videos, a new instance of MediaPlayer will be created in reset(). - private MediaPlayer mPlayer; + // Switching between inline and full screen will also create a new instance. + protected MediaPlayer mPlayer; + + // This will be set up every time we create the Video View object. + // Set to true only when switching into full screen while playing + protected boolean mAutostart; + + // We need to save such info. + protected String mUri; + protected Map<String, String> mHeaders; - private static HTML5VideoView mInstance = new HTML5VideoView(); + // The timer for timeupate events. + // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate + protected static Timer mTimer; - // Video control FUNCTIONS: + // The spec says the timer should fire every 250 ms or less. + private static final int TIMEUPDATE_PERIOD = 250; // ms + + // common Video control FUNCTIONS: public void start() { if (mCurrentState == STATE_PREPARED) { mPlayer.start(); - mReadyToUseSurfTex = true; } } public void pause() { - mPlayer.pause(); + if (mCurrentState == STATE_PREPARED && mPlayer.isPlaying()) { + mPlayer.pause(); + } + if (mTimer != null) { + mTimer.purge(); + } } public int getDuration() { - return mPlayer.getDuration(); + if (mCurrentState == STATE_PREPARED) { + return mPlayer.getDuration(); + } else { + return -1; + } } public int getCurrentPosition() { - return mPlayer.getCurrentPosition(); + if (mCurrentState == STATE_PREPARED) { + return mPlayer.getCurrentPosition(); + } + return 0; } public void seekTo(int pos) { @@ -88,54 +109,51 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{ } public void stopPlayback() { - mPlayer.stop(); + if (mCurrentState == STATE_PREPARED) { + mPlayer.stop(); + } } - private void reset(int videoLayerId) { + public boolean getAutostart() { + return mAutostart; + } + + // Every time we start a new Video, we create a VideoView and a MediaPlayer + public void init(int videoLayerId, int position, boolean autoStart) { mPlayer = new MediaPlayer(); mCurrentState = STATE_NOTPREPARED; mProxy = null; mVideoLayerId = videoLayerId; - mReadyToUseSurfTex = false; + mSaveSeekTime = position; + mAutostart = autoStart; } - public static HTML5VideoView getInstance(int videoLayerId) { - // Every time we switch between the videos, a new MediaPlayer will be - // created. Make sure we call the m_player.release() when it is done. - mInstance.reset(videoLayerId); - return mInstance; + protected HTML5VideoView() { } - private HTML5VideoView() { - // This is a singleton across WebViews (i.e. Tabs). - // HTML5VideoViewProxy will reset the internal state every time a new - // video start. - } + protected static Map<String, String> generateHeaders(String url, + HTML5VideoViewProxy proxy) { + boolean isPrivate = proxy.getWebView().isPrivateBrowsingEnabled(); + String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate); + Map<String, String> headers = new HashMap<String, String>(); + if (cookieValue != null) { + headers.put(COOKIE, cookieValue); + } + if (isPrivate) { + headers.put(HIDE_URL_LOGS, "true"); + } - public void setMediaController(MediaController m) { - this.setMediaController(m); + return headers; } - public void setVideoURI(String uri, Map<String, String> headers) { + public void setVideoURI(String uri, HTML5VideoViewProxy proxy) { // When switching players, surface texture will be reused. - mPlayer.setTexture(getSurfaceTextureInstance()); + mUri = uri; + mHeaders = generateHeaders(uri, proxy); - // When there is exception, we could just bail out silently. - // No Video will be played though. Write the stack for debug - try { - mPlayer.setDataSource(uri, headers); - mPlayer.prepareAsync(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } + mTimer = new Timer(); } - // TODO [FULL SCREEN SUPPORT] - // Listeners setup FUNCTIONS: public void setOnCompletionListener(HTML5VideoViewProxy proxy) { mPlayer.setOnCompletionListener(proxy); @@ -150,43 +168,47 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{ mPlayer.setOnPreparedListener(this); } - // Inline Video specific FUNCTIONS: + // Normally called immediately after setVideoURI. But for full screen, + // this should be after surface holder created + public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) { + // SurfaceTexture will be created lazily here for inline mode + decideDisplayMode(); - public SurfaceTexture getSurfaceTexture() { - return mSurfaceTexture; - } + setOnCompletionListener(proxy); + setOnPreparedListener(proxy); + setOnErrorListener(proxy); - public void deleteSurfaceTexture() { - mSurfaceTexture = null; - return; - } - - // SurfaceTexture is a singleton here , too - private SurfaceTexture getSurfaceTextureInstance() { - // Create the surface texture. - if (mSurfaceTexture == null) - { - mTextureNames = new int[1]; - GLES20.glGenTextures(1, mTextureNames, 0); - mSurfaceTexture = new SurfaceTexture(mTextureNames[0]); + // When there is exception, we could just bail out silently. + // No Video will be played though. Write the stack for debug + try { + mPlayer.setDataSource(mUri, mHeaders); + mPlayer.prepareAsync(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); } - return mSurfaceTexture; } - public int getTextureName() { - return mTextureNames[0]; - } + // Common code public int getVideoLayerId() { return mVideoLayerId; } - public boolean getReadyToUseSurfTex() { - return mReadyToUseSurfTex; - } + private static final class TimeupdateTask extends TimerTask { + private HTML5VideoViewProxy mProxy; - public void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) { - mSurfaceTexture.setOnFrameAvailableListener(l); + public TimeupdateTask(HTML5VideoViewProxy proxy) { + mProxy = proxy; + } + + @Override + public void run() { + mProxy.onTimeupdate(); + } } @Override @@ -195,6 +217,9 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{ seekTo(mSaveSeekTime); if (mProxy != null) mProxy.onPrepared(mp); + + mTimer.schedule(new TimeupdateTask(mProxy), TIMEUPDATE_PERIOD, TIMEUPDATE_PERIOD); + } // Pause the play and update the play/pause button @@ -205,7 +230,42 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{ proxy.dispatchOnPaused(); } } - mReadyToUseSurfTex = false; + } + + // Below are functions that are different implementation on inline and full- + // screen mode. Some are specific to one type, but currently are called + // directly from the proxy. + public void enterFullScreenVideoState(int layerId, + HTML5VideoViewProxy proxy, WebView webView) { + } + + public boolean isFullScreenMode() { + return false; + } + + public SurfaceView getSurfaceView() { + return null; + } + + public void decideDisplayMode() { + } + + public void prepareForFullScreen() { + } + + public boolean getReadyToUseSurfTex() { + return false; + } + + public SurfaceTexture getSurfaceTexture() { + return null; + } + + public void deleteSurfaceTexture() { + } + + public int getTextureName() { + return 0; } } |
