summaryrefslogtreecommitdiff
path: root/core/java/android/webkit/HTML5VideoView.java
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2011-03-02 15:09:34 -0800
committerTeng-Hui Zhu <ztenghui@google.com>2011-03-10 16:58:24 -0800
commit661e8b1f21f03ea429ff34f8fdb58b68a5049092 (patch)
tree5912b8fd1ec3210c5959c198a72d3f21bd5fbb49 /core/java/android/webkit/HTML5VideoView.java
parentdc8b70cabc23316e349aaf2fe03bcc830dd66e6c (diff)
Inline HTML5 Video support
Use the HTML5VideoView to make inline HTML5 video possible. Full screen support will be the next step. The native side change is at 101310. bug:3506407, 2126902 Change-Id: I012f33a4d0c7b83d37b184fceb3923e1fb277b80
Diffstat (limited to 'core/java/android/webkit/HTML5VideoView.java')
-rw-r--r--core/java/android/webkit/HTML5VideoView.java211
1 files changed, 211 insertions, 0 deletions
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
new file mode 100644
index 000000000000..2312160f5c66
--- /dev/null
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -0,0 +1,211 @@
+
+package android.webkit;
+
+import android.graphics.SurfaceTexture;
+import android.media.MediaPlayer;
+import android.util.Log;
+import android.webkit.HTML5VideoViewProxy;
+import android.widget.MediaController;
+import android.opengl.GLES20;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @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;
+
+ // 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;
+
+ // We only need state for handling seekTo
+ private int mCurrentState;
+
+ // Basically for calling back the OnPrepared in the proxy
+ private HTML5VideoViewProxy mProxy;
+
+ // Save the seek time when not prepared. This can happen when switching
+ // video besides initial load.
+ private int mSaveSeekTime;
+
+ // This is used to find the VideoLayer on the native side.
+ private 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;
+
+ private static HTML5VideoView mInstance = new HTML5VideoView();
+
+ // Video control FUNCTIONS:
+ public void start() {
+ if (mCurrentState == STATE_PREPARED) {
+ mPlayer.start();
+ mReadyToUseSurfTex = true;
+ }
+ }
+
+ public void pause() {
+ mPlayer.pause();
+ }
+
+ public int getDuration() {
+ return mPlayer.getDuration();
+ }
+
+ public int getCurrentPosition() {
+ return mPlayer.getCurrentPosition();
+ }
+
+ public void seekTo(int pos) {
+ if (mCurrentState == STATE_PREPARED)
+ mPlayer.seekTo(pos);
+ else
+ mSaveSeekTime = pos;
+ }
+
+ public boolean isPlaying() {
+ return mPlayer.isPlaying();
+ }
+
+ public void release() {
+ mPlayer.release();
+ }
+
+ public void stopPlayback() {
+ mPlayer.stop();
+ }
+
+ private void reset(int videoLayerId) {
+ mPlayer = new MediaPlayer();
+ mCurrentState = STATE_NOTPREPARED;
+ mProxy = null;
+ mVideoLayerId = videoLayerId;
+ mReadyToUseSurfTex = false;
+ }
+
+ 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;
+ }
+
+ private HTML5VideoView() {
+ // This is a singleton across WebViews (i.e. Tabs).
+ // HTML5VideoViewProxy will reset the internal state every time a new
+ // video start.
+ }
+
+ public void setMediaController(MediaController m) {
+ this.setMediaController(m);
+ }
+
+ public void setVideoURI(String uri, Map<String, String> headers) {
+ // When switching players, surface texture will be reused.
+ mPlayer.setTexture(getSurfaceTextureInstance());
+
+ // 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();
+ }
+ }
+
+ // TODO [FULL SCREEN SUPPORT]
+
+ // Listeners setup FUNCTIONS:
+ public void setOnCompletionListener(HTML5VideoViewProxy proxy) {
+ mPlayer.setOnCompletionListener(proxy);
+ }
+
+ public void setOnErrorListener(HTML5VideoViewProxy proxy) {
+ mPlayer.setOnErrorListener(proxy);
+ }
+
+ public void setOnPreparedListener(HTML5VideoViewProxy proxy) {
+ mProxy = proxy;
+ mPlayer.setOnPreparedListener(this);
+ }
+
+ // Inline Video specific FUNCTIONS:
+
+ public SurfaceTexture getSurfaceTexture() {
+ return mSurfaceTexture;
+ }
+
+ 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]);
+ }
+ return mSurfaceTexture;
+ }
+
+ public int getTextureName() {
+ return mTextureNames[0];
+ }
+
+ public int getVideoLayerId() {
+ return mVideoLayerId;
+ }
+
+ public boolean getReadyToUseSurfTex() {
+ return mReadyToUseSurfTex;
+ }
+
+ public void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) {
+ mSurfaceTexture.setOnFrameAvailableListener(l);
+ }
+
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mCurrentState = STATE_PREPARED;
+ seekTo(mSaveSeekTime);
+ if (mProxy != null)
+ mProxy.onPrepared(mp);
+ }
+
+ // Pause the play and update the play/pause button
+ public void pauseAndDispatch(HTML5VideoViewProxy proxy) {
+ if (isPlaying()) {
+ pause();
+ if (proxy != null) {
+ proxy.dispatchOnPaused();
+ }
+ }
+ mReadyToUseSurfTex = false;
+ }
+
+}